본문 바로가기

DevOps & Infra/Docker

[Infrastructure/Docker] 튜토리얼 살펴보기#002. 이미지 만들기

예제 코드 다운로드

튜토리얼 웹 페이지(http://localhost/tutorial/our-application/)에서 [ Download the ZIP ]을 클릭하여 예제 코드를 다운로드 받습니다. 압축을 풀고, 임의의 IDE를 사용하여 프로젝트를 엽니다. 튜토리얼에서 제공하는 프로젝트는 Node.js 기반으로 작성되었습니다. 

이미지 만들기

애플리케이션을 빌드하려면, 도커 파일(Dockerfile)을 사용합니다. 도커파일은 이미지를 만들기 위해 사용되는 텍스트 기반의 명령 스크립트입니다.

package.json 파일과 같은 경로에 Dockerfile 이름의 도커 파일을 생성합니다. 도커 파일의 내용은 다음과 같이 입력합니다(지금 입력한 내용은 약간의 오류를 포함합니다).

FROM node:12-alpine
# Adding build tools to make yarn install work on Apple silicon / arm64 machines
RUN apk add --no-cache python2 g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

작성한 도커 파일에 .txt와 같은 확장자가 포함되지는 않았는지 주의하세요. 일부 IDE에서는 자동으로 확장자가 추가 될 수 있습니다. 도커 파일은 확장자를 포함하면 오류가 발생하니, 반드시 확장자를 확인해주세요.

이제 터미널을 실행하여 도커 파일이 위치한 경로로 이동합니다. 그리고 터미널에서 다음 명령문을 입력합니다.

$ docker build -t getting-started .

입력한 명령문은 도커 파일을 사용하여 이미지를 생성합니다. 명령문이 실행되면 필요한 레이어를 다운로드합니다. 우리가 도커 파일에서 node:12-alpine 명령을 입력하여 기본 이미지를 사용하도록 지시했기 때문입니다.

명령문에서 -t 플래그는 이미지를 생성할 때 붙이는 태그를 지정합니다. 명령문이 실행되면, 도커 데스크탑 등에서 태그(getting-started)를 갖는 이미지를 찾을 수 있습니다.

명령문의 마지막에 포함된 명령 도트(.)는 도커가 도커 파일을 찾을 때, 명령문이 실행되는 현재 디렉토리를 기준으로 찾도록 지시합니다.

$ docker build -t getting-started .
[+] Building 29.8s (11/11) FINISHED                                                                                                                                                                       
 => [internal] load build definition from Dockerfile                                                                                                                                                 0.0s
 => => transferring dockerfile: 357B                                                                                                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/node:12-alpine                                                                                                                                    3.2s
 => [auth] library/node:pull token for registry-1.docker.io                                                                                                                                          0.0s
 => [1/5] FROM docker.io/library/node:12-alpine@sha256:dfa564312367b1a8fca8db7ae4bae102b28e68b39ebcb7b17022c938f105846b                                                                              3.0s
 => => resolve docker.io/library/node:12-alpine@sha256:dfa564312367b1a8fca8db7ae4bae102b28e68b39ebcb7b17022c938f105846b                                                                              0.0s
 => => sha256:f150ebf9402f0dd6a9c4cb208ed64884cfa7c8a6ccae3f749a7b12156c25ad88 1.16kB / 1.16kB                                                                                                       0.0s
 => => sha256:1b156b4c3ee8964408ef97a9afa543b5cb15067ffb58941db9d085f747ce2785 6.54kB / 6.54kB                                                                                                       0.0s
 => => sha256:8769eb813ad53f772e80559e417a3e3419b5651134dd217e66bdec74d9722038 24.91MB / 24.91MB                                                                                                     1.0s
 => => sha256:7025e9ac362ee7e80cd0cf161c010c0f4a42631fdcd0961352c4ad545372a53d 2.36MB / 2.36MB                                                                                                       0.6s
 => => sha256:1efe07d207fa5b94c00d1ed34b8c08b2c2b5161ee27d4dea77d2ae25c07aa267 450B / 450B                                                                                                           0.7s
 => => sha256:dfa564312367b1a8fca8db7ae4bae102b28e68b39ebcb7b17022c938f105846b 1.43kB / 1.43kB                                                                                                       0.0s
 => => extracting sha256:8769eb813ad53f772e80559e417a3e3419b5651134dd217e66bdec74d9722038                                                                                                            1.4s
 => => extracting sha256:7025e9ac362ee7e80cd0cf161c010c0f4a42631fdcd0961352c4ad545372a53d                                                                                                            0.1s
 => => extracting sha256:1efe07d207fa5b94c00d1ed34b8c08b2c2b5161ee27d4dea77d2ae25c07aa267                                                                                                            0.0s
 => [internal] load build context                                                                                                                                                                    0.1s
 => => transferring context: 4.62MB                                                                                                                                                                  0.1s
 => [2/5] RUN apk add --no-cache python2 g++ make                                                                                                                                                    5.6s
 => [3/5] WORKDIR /app                                                                                                                                                                               0.0s
 => [4/5] COPY . .                                                                                                                                                                                   0.0s
 => [5/5] RUN yarn install --production                                                                                                                                                             16.2s
 => exporting to image                                                                                                                                                                               1.7s
 => => exporting layers                                                                                                                                                                              1.7s
 => => writing image sha256:dd98a0f5b5d3b4a6f2e04146b40d6e29879aa59b63827fc63ca95fa915ea07cf                                                                                                         0.0s
 => => naming to docker.io/library/getting-started

컨테이너 시작

도커의 run 명령문을 사용하여 컨테이너를 시작 할 수 있습니다. 방금 생성한 이미지의 태그를 활용하여 컨테이너를 시작합니다.

docker run -dp 3000:3000 getting-started

명령문의 -d 플래그는 컨테이너를 백그라운드-데몬에서 동작하게끔 지정합니다. -p 플래그는 호스트 포트와 컨테이너 포트를 맵핑합니다. 예시에서는 getting-started 태그의 이미지를 데몬으로 실행하고, 호스트의 3000번 포트를 이미지가 실행되고 있는 컨테이너에 맵핑합니다.

이제 URL에 다음 주소(http://localhost:3000)를 입력합니다. 컨테이너가 정상적으로 실행되었다면, 웹 브라우저에서 다음 페이지를 출력합니다.

우리가 작성한 도커 파일에서 CMD["node", "src/index.js"]는 컨테이너가 시작 될 때 수행하는 명령문입니다. 컨테이너가 시작되면, Node.js는 src/index.js에서 실행됩니다. 우리가 웹 브라우저에서 입력한 URL은 로컬 머신의 컨테이너에서 실행중인 Node.js의 index.html 파일을 출력합니다.