Docker

[Docker] 3. Containerizing - Dockerfile로 도커 이미지 만들기

big whale 2024. 3. 8. 21:38

Containerizing(컨테이너화)

응용 프로그램과 그에 필요한 모든 종속성을 컨테이너로 묶어서 효율적으로 배포 및 실행할 수 있게 해주는 과정

도커 이미지를 만드는 과정이다.

 

Dockerfile이 Docker image로 빌드되는 과정

현재 디렉토리 상태

app.js와 package.json 등 node.js 앱을 만들기 위한 파일들과 Dockerfile이 있다.

Dockerfile 코드를 살펴보자.

 

Dockerfile 구성

  • Dockerfile은 맨윗줄부터 맨 아랫줄까지 한줄씩 파싱되어 실행된다.
  • 주석(#)이 아닌 줄은 모두 실행되어야 하는 명령어이다. 대소문자를 구별하지 않지만 명령어의 이름은 대문자로만 이루어지는게 보기 편하다.

위의 Dockerfile 각 명령어별 설명

1. FROM alpine

이미지의 맨 아래 레이어에 alpine OS가 쌓인다.

 

2. LABEL

키-값 쌍으로 커스텀 메타데이터를 담는데 사용된다.

 

3. Run apk add --update nodejs npm curl

Alpine apk 패키지를 이용해서 nodejs와 npm을 설치하여 레이어를 생성한다.

 

4. Copy . /src

현재 디렉토리의 app 파일들을 ./src로 복사해주는 레이어를 생성한다.

 

5. WORKDIR /src

작업공간을 /src로 설정한다.

따로 레이어를 만들어 저장하지 않고, 이미지의 config 메타데이터에 더해진다.

 

6. RUN npm install

WORKDIR로 설정했던 /src 폴더에 이전 레이어를 쌓을 때 설치한 npm을 이용해서 의존성 라이브러리들을 전부 받아오는 레이어를 생성한다.

 

7. EXPOSE 8080

TCP 포트 8080을 열어놓는다. 이미지의 메타데이터에 더해진다.

 

8. ENTRYPOINT["node", "./app.js"]

컨테이너가 실행해야 하는 파일을 설정한다. 이미지의 메타데이터로 더해진다.

 

Dockerfile을 이용해 도커 이미지를 빌드해보자.

docker image build -t web:latest .
  • 현재 위치를 빌드 컨텍스트로 삼고, 해당 영역 내에 존재하는 Dockerfile을 읽어들여 이미지를 빌드하겠다.

 

컨테이너를 실행시켜보자.

docker container run -d --name c1 -p 80:8080 web:latest
  • 호스트의 80번 포트로 들어오는 요청을 컨테이너의 8080으로 향하게 한다.
  • 이미 호스트에서 포트번호 80을 다른 용도로 사용중이라면, 사용하지 않는 포트번호로 대체한다.

컨테이너 실행 결과

  • nodejs 앱 컨테이너가 실행중이다.

localhost:80으로 접속해보자

  • 잘 뜬다.

위 설명대로 이미지가 레이어를 쌓았는지 확인해보자.

docker image history web:latest

 

  • SIZE가 0B가 아닌 명령어들은 레이어로 생성된 것들이다.

도커 이미지는 크면 안좋다. 프로덕션을 구동하는 데 꼭 필요한 재료들만 이미지에 담아야 좋다. 문제는 이미지를 작게 유지하는게 어렵다는 것이다. Dockerfile에 RUN 명령어를 추가할 때마다 이미지에 새 레이어가 하나가 생긴다.

 

또 다른 문제는 빌드시점때만 사용되는 도구들 역시 이미지에 쌓인다는 것이다. 이 도구들은 프로덕션 레벨에서는 사용되지 않기 때문에 이미지 크기가 커지는 요인이다.

 

프로덕션 이미지 크기 줄이는 방법 - Multi stage

  • FROM 명령어는 stage를 생성하는데, 여러개의 FROM을 사용해서 이전 stage의 데이터를 복사해 오는 기법

Multi stage 적용된 Dockerfile 예시

  • FROM node:latest AS storefront
  • FROM maven:latest AS appserver
  • FROM java:8-jdk-alpine

이렇게 총 3개의 FROM이 있고 세번째 FROM을 보면 COPY 명령어가 있는데 이전 FROM을 통해서 생성한 빌드 결과물 중 필요한 것만 복사해오는 과정이다.

 

빌드 결과

하나의 Dockerfile이 6개의 이미지를 만들었고, 최종 생성된 프로덕션 이미지는 multi:stage 이미지이다.