package.json : 프로젝트의 정보와 프로젝트에서 사용 중인 패키지의 의존성을 관리하는 곳
{
"name": "nodejs-docker-app",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start" : "node server.js"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"express" : "4.17.1"
}
}
server.js : 시작점으로서 가장 먼저 시작되는 파일
const express = require('express');
const PORT = 8080;
//APP
const app = express();
app.get('/', (req, res) => {
res.send("Hello World")
});
app.listen(PORT);
console.log("Server is running")
앞서 만든 node.js앱을 이미지로 만들기 위해 Dockerfile을 작성해보자.
FROM node:10
WORKDIR /usr/src/app
COPY ./ ./
RUN npm install
CMD ["node", "server.js"]
COPY ./ ./
: "npm install" 명령어는 package.json 파일을 대상으로 실행된다. 하지만 임시컨테이너에는 package.json이 없다. 마찬가지로 "server.js" 명령어 또한 server.js 파일을 필요로 한다. 따라서 현재 폴더 내 모든 파일(package.json, server.js)을 임시컨테이너로 복사해줘야 한다.
WORKDIR
: base 이미지인 node 이미지에는 여러 파일들이 있는데 COPY 명령어에 의해 이미지 안으로 Dockerfile, package.json, package-lock.json, node_module, server.js 등이 들어온다. 만약 새로 추가되는 파일과 기존 파일들의 이름이 겹치면 덮어 씌워져 버리기 때문에 애플리케이션을 위한 모든 소스 파일들은 WORK 디렉토리를 따로 만들어서 보관하는 것이 좋다. WORKDIR은 이미지 안에서 애플리케이션 소스 코드들을 갖고 있을 디렉토리를 생성해준다.
빌드
docker build -t hal8h/nodejs ./
컨테이너 실헹
d : 컨테이너 실행만 하고 터미널로 나옴
docker run -d -p 5000:8080 hal8h/nodejs
소스 코드가 변경될 때마다 npm install을 통해 종속성 파일들을 다시 다운받는것은 비효율적이다. 캐시를 통해 빌드를 최적화해보자.
완성본 Dockerfile에는 Run 위에 COPY package.json ./이 하나가 추가되고 원래의 COPY가 RUN 아래로 내려갔다. 그 이유는 npm install 할때 불필요한 다운로드를 피하기 위해서다(캐시 활용). 완성본의 Dockerfile에서는 package.json을 먼저 COPY 하기 때문에 소스코드(server.js)가 변경되어도 캐시로 인해 다시 종속성을 설치 받는 과정이 생략된다.
아래와 같이 Dockerfile을 수정하자.
FROM node:10
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY ./ ./
CMD ["node", "server.js"]
기존에는 COPY라는 명령어로 소스 파일들을 컨테이너에 넣어줬다. 하지만 소스 코드를 변경할 때마다 이미지를 다시 빌드해야하는 번거로움이 있다. Volume은 도커 컨테이너에서 local에 있는 파일들을 참조하는데 이를 이용하면 Local에서 소스 코드가 변경될 시 자동으로 컨테이너에 반영할 수 있다.
docker run -d -p 5000:8080 -v /usr/src/app/node_modules -v ${pwd}:/usr/src/app <이미지 아이디>
-v /usr/src/app/node_modules : host 디렉토리에 node_module은 없기에 컨테이너에 매핑을 하지 말라고 하는 것.
-v ${pwd}:/usr/src/app : pwd 경로에 있는 디렉토리 혹은 파일을 /usr/src/app 경로에서 참조(local <- 컨테이너).
이제부터는 소스 코드를 변경하고 노드 앱이 있는 컨테이너를 껐다가 다시 키면 빌드 없이 변경사항이 자동으로 앱에 반영된다.