[Docker] 11. Dockerfile
카테고리: DOCKER
태그: docker
[Docker] 11. Dockerfile
🔔 Dockerfile이란?
-
Docker에서는 인프라 구성을 기술한 파일을 Dockerfile이라고 한다.
-
전 챕터에서는 Docker 이미지 작성하려면 베이스가 되는 도커 이미지를 바탕으로 도커 컨테이너를 생성하고, 생성한 도커 컨테이너 안에서 OS의 설정이나 미들웨어의 설치, 파라미터의 설정 등을 수동으로 수행 그리고 만들어진 컨테이너에서 서버를 구축한 상태를 바탕으로 도커 이미지를 생성했다.
-
이를 위해서는 다음과 같은 정보를 인프라 설계서나 파라미터 시트 등에 별도로 남겨 둘 필요가 있다.
-
베이스가 될 Docker 이미지
-
Docker 컨테이너 안에서 수행한 조작(명령)
-
환경변수 등의 설정
-
Docker 컨테이너 안에서 작동시켜둘 데몬 실행
-
-
Dockerfile은 이와 같이 Docker 상에서 작동시킬 컨테이너의 구성 정보를 기술하기 위한 파일이다.
(a) Dockerfile에 기술된 구성 정보를 바탕으로 Docker 이미지를 작성 - docker build 명령
docker build -t [생성할 이미지명]:[태그명] [Dockerfile의 위치]
# 파일명을 지정한 docker build 명령 실행
docker build -t sample -f Dockerfile.base .
# 표준 입력에서의 빌드
docker build - < Dockerfile
(b) Docker 이미지의 레이어 구조
Dockerfile을 빌드하여 이미지를 작성하면 Dockerfile의 명령별로 이미지를 작성한다.
# STEP:1 Ubuntu (베이스 이미지)
FROM ubuntu:latest
# STEP:2 Nginx 설치
RUN apt-get update && apt-get install -y -q nginx
# STEP:3 파일 복사로
COPY index.html /usr/share/nginx/html
# STEP:4 Nginx 시작
CMD ["nginx", "-g", "daemon off;"]
$ docker build -t webap .
Sending build context to Docker daemon 1.307G GB
Step 1/4 : FROM ubuntu:latest
---> 0458a4468cbc # <-- 첫 번째 이미지 작성
~중략~
Step 2/4 : RUN apt-get update && apt-get install -y -q nginx
---> 9e6b06ec7d4f # <-- 두 번째 이미지 작성
~중략~
Step 3/4 : COPY index.html /usr/share/nginx/html
---> d66d95434d9d # <-- 세 번째 이미지 작성
~중략~
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
---> a6f8f57f1588 # <-- 네 번째 이미지 작성
작성한 이미지는 다른 이미지와도 공유되는데, 예를 들어 아래 그림과 같이 공통의 베이스 이미지를 바탕으로 여러 개의 이미지를 작성한 경우, 베이스 이미지의 레이어가 공유된다. (이와 같이 이미지 겹침으로써 도커에서는 디스크의 용량을 효율적으로 이용함)

🔔 Dockerfile 작성
📜 명령 및 데몬 실행
(a) 베이스 이미지 지정 - FROM
FROM [이미지명]
FROM [이미지명]:[태그명]
FROM [이미지명]@[다이제스트]
# 다이제스트 확인
docker image ls --digests tensorflow/tensorflow
(b) 명령 실행 - RUN
베이스 이미지에 대해 애플리케이션/미들웨어를 설치 및 설정, 환경 구축을 위한 명령 실행 등과 같은 명령을 실행
RUN [실행하고 싶은 명령]
# Shell 형식
RUN apt-get -y install nginx
RUN echo Shell 형식 입니다.
# Exec 형식
RUN ["/bin/bash", "-c", "apt-get -y install nginx"]
RUN ["echo", "Exec 형식 입니다"]
RUN ["/bin/bash", "-c", "echo 'Exec 형식에서 bash를 사용'"]
(c) 데몬 실행 - CMD
이미지를 바탕으로 생성된 컨테이너 안에서 명령을 실행하려면 CMD를 사용
CMD [실행하고 싶은 명령]
# Shell 형식
CMD nginx -g 'daemon off;'
# Exec 형식
RUN ["nginx", "-g", "daemon off;"]
(d) 데몬 실행 - ENTRYPOINT
ENTRYPOINT로 지정된 명령은 컨테이너가 수행될 때 반드시 지정된 명령을 수행
CMD로 짖정된 명령은 컨테이너가 실행될 때 인자 값을 주게 되면 Dockerfile에 지정된 CMD 값을 대신하여 지정한 인자값으로 변경하여 실행되자만, ENTRYPOINT는 덮어쓰지 않는다.
ENTRYPOINT [실행하고 싶은 명령]
# Shell 형식
ENTRYPOINT nginx -g 'daemon off;'
# Exec 형식
ENTRYPOINT ["nginx", "-g", "daemon off;"]
(e) 빌드 완료 후에 실행되는 명령 - ONBUILD
ONBUILD는 처음 사용한 Dockerfile에서 빌드할 때 실행되는 명령이 아니라, ONBUILD 명령을 사용했던 이미지를 다른 Dockerfile에서 베이스 이미지로 사용하여 빌드했을 때 동작한다.
ONBUILD [실행하고 싶은 명령]
# 예시
ONBUILD ADD website.tar /var/www/html
-
예를 들면, 인프라 환경 구축과 관련된 부분을 베이스 이미지로 작성하고, 이때 ONBUILD 명령으로 이미지 안에 개발한 프로그램을 전개하는 명령(ADD, COPY 등)을 지정한다.
-
이러면 개발자는 애플리케이션 구축 부분을 코딩하고 이미 작성이 끝난 베이스 이미지를 바탕으로 한 이미지를 작성하고 이 이미지 안에는 프로그래밍이 끝난 업무 애플리케이션이 전개된다.
(f) 시스템 콜 시그널의 설정 - STOPSIGNAL
컨테이너를 종료할 때에 송신하는 시그널을 설정할 때 사용하는 명령 (시그널 번호 or 시그널명을 지정)
STOPSIGNAL [실행하고 싶은 명령]
(g) 컨테이너의 헬스 체크 명령 (HEALTHCHECK 명령)
컨테이너 안의 프로세스가 정상적으로 동작하고 있는지를 체크
HEALTHCHECK [옵션] CMD [실행할 명령]
# 예시, 5분마다 가동 중인 웹 서버의 메인 페이지를 3초 안에 표시할 수 있는지 없는지 확인
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
| 옵션 | 설명 |
|---|---|
| –interval=n | 헬스 체크 간격 (기본값 : 30s) |
| –timeout=n | 헬스 체크 타임아웃 (기본값 : 30s) |
| –retries=N | 타임아웃 횟수 (기본값 : 3) |
📜 환경변수 및 네트워크 설정
(a) 환경변수 설정 - ENV
# key value 형식
ENV [key] [value]
# key=value 형식
ENV [key]=[value]
# 예시1) key value 형식
ENV myName "choi"
ENV myOrder gin whisky calvados
ENV myNickName ch
# 예시2) key=value 형식
ENV myName="choi" \
myOrder=gin\ whisky\ calvados \
myNickName=ch
(b) 작업 디렉터리 지정 - WORKDIR
WORKDIR [작업 디렉터리 지정]
# 절대 경로/상대 경로를 사용한 WORKDIR 명령
WORKDIR /first
WORKDIR second
WORKDIR third
RUN ["pwd"]
# WORKDIR 명령으로 환경변수를 사용한 예
ENV DIRPATH /first
ENV DIRNAME second
WORKDIR $DIRPATH/$DIRNAME
RUN ["pwd"]
(c) 사용자 지정 - USER
RUN, CMD, ENTRYPOINT 명령을 실행하기 위한 사용자를 지정할 때 사용
USER [사용자명/UID]
(d) 라벨 지정 - LABEL
이미지에 버전 정보나 작성자 정보, 코멘트 등과 같은 정보를 제공할 때 사용 (LABEL 명령으로 지정한 정보는 docker image inspect로 확인할 수 있다.)
LABEL [key]=[value]
# 예시
LABEL maintainer="choi <test@gmail.com>"
LABEL title="WevAP"
LABEL version="1.0"
LABEL description="This image is WebApplicationServer"
(e) 포트 설정 - EXPOSE
EXPOSE 명령은 도커에게 실행 중인 컨테이너가 listen하고 있는 네트워크를 알려주고, 또한 docker run 명령의 -p 옵션을 사용할 떄 어떤 포트를 호스트에 공개할지를 정의한다.
EXPOSE <포트번호>
(f) Dockerfile 내 변수의 설정 - ARG
Dockerfile 안에서 사용할 변수를 정의할 때 사용, ARG 명령을 사용하면 변수의 값에 따라 생성되는 이미지의 내용을 바꿀 수 있다.
ARG <이름>[=기본값]
(g) 기본 쉘 설정 - SHELL
Shell 형식으로 명령을 실행할 때 사용, 기본값 [“/bin/bash”, “-c”]
SHELL ["shell 경로", "파라미터"]
📜 파일 설정
(a) 파일 및 디렉터리 추가 - ADD
호스트상의 파일 또는 디렉터리를 이미지에 추가할 때 사용
ADD <호스트의 파일 경로> <Docker 이미지의 파일 경로>
ADD ["<호스트의 파일 경로>" "<Docker 이미지의 파일 경로>"]
-
이미지에 추가 하고 싶은 파일이 원격 파일 URL인 경우, 추가한 파일의 퍼미션이 600이 된다.
-
ADD 명령은 인증을 지원하지 안기 때문에 원격 파일의 다운로드에 인증이 필요한 경우, RUN 명령에서 wget, curl 명령을 사용한다.
-
호스트의 파일이 tar 아카이브거나 압축 포맷일 때는 디렉터리로 압축을 풀지만, 원격 URL로부터 다운로드한 리소스는 압축이 풀리지 않는다.
(b) 빌드에 불필요한 파일 제외
도커에서 빌드를 하면 빌드를 실행한 디렉터리 아래에 있는 모든 파일이 도커 데몬으로 전송되기 때문에 빌드에서 제외하고 싶은 파일이 있는 경우 “.dockerignore”라는 이름의 파일 안에 해당 파일명을 기술하면 된다.
$ ls -al
total 12
drwxr-sr-x 2 docker test 100 Jun 11 00:35 ./
drwxr-sr-x 6 docker test 180 Jun 11 23:35 ../
-rw-r--r-- 1 docker test 180 Jun 11 00:30 .dockerignore
-rw-r--r-- 1 docker test 180 Jun 11 00:33 Dockerfile
-rw-r--r-- 1 docker test 180 Jun 11 00:31 dummyfile
$ cat .dockerignore
dummyfile
$ cat Dockerfile
FROM ubuntu:latest
ADD dummyfile /tmp/dummyfile
$ docker build -t sample .
Sedning build context to Docker daemon 3.072 kB
Sedning build context to Docker daemon
Step 1/2 : FROM ubuntu:latest
---> 0458a4468cbc
Step 2/2 : ADD dummyfile /tmp/dummyfile
ADD failed: stat /var/lib/docker/tmp/docker-builder166832226/dummyfile: no such file or directory
(c) 파일 복사 - COPY
호스트상의 파일 또는 디렉터리를 이미지에 복사할 떄 사용
COPY <호스트의 파일 경로> <Docker 이미지의 파일 경로>
COPY ["<호스트의 파일 경로>" "<Docker 이미지의 파일 경로>"]
- ADD 명령은 원격 파일의 다운로드나 아카이브의 압축 해제 등과 같은 기능을 갖고 있지만, COPY 명령은 호스트상의 파일을 이미지 안으로 복사하는 처리만 한다.
(d) 볼륨 마운트 - VOLUME
VOLUME 명령은 지정한 이름의 마운트 포인트를 작성하고, 호스트나 그 외 다른 컨테이너로부터 볼륨의 외부 마운트를 수행한다.
VOLUME ["/마운트 포인트"]
# 예시
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
댓글 남기기