* Dockerfile이란?

도커 명령어로 컨테이너를 구성하기 위해서는 컨테이너 생성, 컨테이너 안에서 OS설정, 미들웨어 설치, 파라미터 설정 등은 모두 직접 수행해야 한다. 이러한 일련의 작업을 자동으로 수행하도록 스크립트로 만든것이 dockerfile이다. 이러한 Dockerfile은 필요한 환경설정이 모두 세팅된 image를 만드는 데 목적이 있으며, 또한 자동화로써 사용할 수 있고 스크립트이므로 변경해서 재사용할수도 있다.이러한 도커파일의 내용은 아래와 같은 정보들을 기술한다.

 

1. 베이스가 될 도커 이미지

2. 도커 컨테이너 안에서 수행할 명령, 조작 등

3. 환경변수 등의 설정

4. 도커 컨테이너 안에서 작동시킬 데몬 실행

 

* Dockerfile 구문 기본

Dockerfile은 텍스트 형식이며 확장자는 없다. 만들기 위해서는 어떤 에디터도 상관없다. 메모장도 좋고, vi editor, notepad++, ultraedit 등등 어떤 프로그램도 상관없다. visual studio code는 dockerfile 작성을 위한 확장파일을 제공하므로 좀 더 편하게 사용할 수 있다. 이러한 텍스트 파일의 이름은 기본적으로 Dockerfile 이라는 이름을 사용한다. 만약 이름을 변경하는 경우, 이미지 build 시 따로 옵션을 줘서 해당 파일명을 명시해줘야 한다. 

 

기본 서식은 "명령 인수" 형식이다. FROM centos:centos7 이런 식. 또한 명령 부분은 대소문자를 가리지는 않지만, 가독성을 위해 관례적으로 대문자를 사용한다. 또한 주석도 가능하며 주석은 맨 앞에 #을 붙이면 된다. 명령의 종류는 아래와 같으며, 각 상세 명령의 사용과 설명은 맨 아래 Docker 명령 상세 설명 부분을 참고한다.

명령

설명

상세

FROM

베이스 이미지 지정

docker 컨테이너를 어떤 docker 이미지로부터 생성할지 기술

RUN

명령 실행

from에서 지정한 베이스 이미지에 대해 수행하는 명령

CMD

컨테이너 실행 명령

from에서 지정한 베이스 이미지에 대해 데몬을 실행하는데 자주 사용

LABEL

라벨 설정

도커파일에 기술할 기타정보들을 기록한다. 만든사람, 버전 등

EXPOSE

포트 익스포트

포트를 오픈한다.

ENV

환경변수

도커파일 안에서 환경변수를 설정한다.

ADD

파일/디렉토리 추가

 

COPY

파일 복사

 

ENTRYPOINT

컨테이너 실행 명령

cmd와 동일하나 컨테이너 생성명령 수행시 무조건 우선적이다.

VOLUME

볼륨 마운트

 

USER

사용자 지정

특정 명령을 수행할 때 사용할 사용자를 명시한다.

WORKDIR

작업 디렉토리

명령어가 실행될 경로를 지정

ARG

dockerfile 안의 변수

도커파일에서 변수를 만들 때 사용

ONBUILD

빌드 완료 후 실행되는 명령

빌드한 후 나온 이미지를 다시 빌드할 때 실행되는 명령

STOPSIGNAL

시스템 콜 시그널 설정

컨테이너 종료시 사용할 시그널 설정

HEALTHCHECK

컨테이너의 헬스체크

일정 주기로 컨테이너의 헬스를 체크하여 결과를 inspect로 볼수있게 한다.

SHELL

기본 쉘 설정

도커파일에서 사용할 쉘 지정

2020/06/15 - [Docker Basic] - [Docker Basic] 17. Dockerfile 상세 명령

 

* Dockerfile 만들기

1. docker build 명령

docker build 명령은 dockerfile에 기술된 구성정보를 바탕으로 도커 이미지를 생성한다. 즉 dockerfile을 사용하는 프로세스는 다음과 같은 절차로 작업이 진행되게 된다. 

 

dockerfile 생성 → docker build 로 이미지 생성 생성된 이미지로 docker container run 수행

 

dockerfile에 명시된 이미지가 없는 경우 자동으로 다운로드를 받으며, 그것이 베이스 이미지가 된다. 그리고 이후 명령어들을 모두 수행한 다음, 그 상태를 이미지로 만든다. 만들어진 이미지의 이름을 build 명령 수행 시 명시해야 한다. 또한 Dockerfile 그대로 이름을 쓰지 않고 따로 임의의 파일명을 사용하는 경우, -f 옵션을 사용해야 한다. 참고로, 임의의 파일명을 쓰는 경우 Docker hub에서 이미지 자동 생성 기능을 사용할 수 없다.

 

형식

docker build -t [생성할이미지명]:[태그명] [dockerfile위치]

 

예시

docker build -t sample -f Dockerfile-base .

- 해당 예시 맨 뒤의 . 은 현재 경로를 의미한다. 현재 경로에 Dockerfile-base 파일이 있는 것.

 

# 참고 : 주의사항 1

Dockerfile을 빌드할 때, 내용을 검증하지 않는다. 있는 그대로 만들 뿐이므로 에러가 있지 않도록 직접 잘 검증해야 한다.

 

# 참고 : 주의사항 2

dockerfile 빌드 시, 해당 dockerfile이 있는 디렉토리 전체의 내용을 모두 docker daemon으로 전송한다. 예를들어 루트디렉토리에 dockerfile을 놓고 build를 실행해버리면 영 좋지 않을 것이다. 따라서 dockerfile은 따로 빈 디렉토리 안에 만들어 놓고 build를 수행해야 한다.

 

# 참고 : 빌드할 때 불필요한 파일 제외하기

도커에서 빌드하면 빌드를 실행한 디렉토리 아래에 있는 모든 파일이 docker 데몬으로 전송된다. 빌드에서 제외하고 싶은 파일이 있는 경우, ".dockerignore" 라는 이름의 파일안에 해당 파일명을 기술하면, 해당 파일은 제외된다. 여러개의 파일을 지정할 때는 줄바꿈을 해서 파일명을 나열한다. 경로 /test에 Dockerfile hello.txt 가 있는데 hello.txt는 제외하고 싶다면, 해당 경로에 .dockerignore를 만들고 내용에 hello.txt를 입력하면 된다. 만약 제외하도록 명시한 파일을 Dockerfile에 ADD 등으로 들어가게 하면, 도커파일 빌드할 때 파일이 없다고 에러가 발생하므로 참고할 것.

 

2. docker history 명령

dockerfile을 빌드한 후 생성된 이미지에 대해 어떤 이미지가 순차적으로 만들어져 있고, 용량은 얼마이고, 이미지ID는 무엇인지 등 상세한 정보를 확인할 수 있다.

docker history 이미지명

이러한 docker history의 결과는 아래서부터 시작하여 맨 위가 끝인 순서로 기록된다. missing 부분은 base image의 history이다. 중요하게 봐야 할 것은 missing이 아닌 부분이며 이것들이 실제로 dockerfile에 기록된 각 step 이다.

 

또한 CREATED BY 아래에 #(nop)라는 부분이 있는데, 그것의 의미는 명령어가 아닌 것들을 의미한다. 명령어는 "실행" 된다. 하지만 #(nop)가 있는것은 "실행"하는 게 아니다. 예를들어 ENV foo=bar 이런것은 "실행"하는 것이 아님.

 

 

 

* Dockerfile과 Docker image

Dockerfile 명령은 해당 스크립트를 build 할 때 각 항목들을 Image Layer 로서 중간 이미지들을 생성한다. 이렇게 하면 다른 이미지를 빌드할 때 이런 중간 이미지들을 내부적으로 재이용하여 빌드의 속도를 높이고 용량 낭비도 줄일 수 있다. 아래 예시를 통해 이미지가 어떻게 사용되는지 확인할 수 있다. 

 

 

예시 : Dockerfile과 Docker image의 관계

 

- 사전정보 1 : Dockerfile 내용

FROM ubuntu:16.04
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

- 사전정보 2 : docker images 명령

사전정보 1에서는 ubuntu:16.04 이미지를 사용한다. 그리고 사전정보 2를 보면 이미 ubuntu 16.04 이미지를 이미 보유한 상태로 확인할 수 있다. 이미지 아이디는 005d2078bdfa 이다. 기억해두자. 이제 다음과 같이 빌드를 수행하면, 아래와 같은 Step을 진행한다.

docker build -t dockerfile_ubuntu-nginx .

 

Step 1/5 : FROM ubuntu:16.04

 ---> 005d2078bdfa

 

Step 2/5 : RUN apt-get -y update && apt-get -y upgrade

 ---> Running in 23ec84a0a536

Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]

Processing triggers for libc-bin (2.23-0ubuntu11) ...

(중략)

Removing intermediate container 23ec84a0a536

 ---> 3d241e1c26f6

 

Step 3/5 : RUN apt-get install -y -q nginx

 ---> Running in a1a6eaaa9313

Reading package lists...

(중략)

Processing triggers for sgml-base (1.26+nmu4ubuntu1) ...

Processing triggers for systemd (229-4ubuntu21.28) ...

Removing intermediate container a1a6eaaa9313

 ---> 90f723b65664

 

Step 4/5 : EXPOSE 80

 ---> Running in 38f032d07f6a

Removing intermediate container 38f032d07f6a

 ---> d62272ebb369

 

Step 5/5 : CMD ["nginx", "-g", "daemon off;"]

 ---> Running in 88d82f578ea5

Removing intermediate container 88d82f578ea5

 ---> c6dca2667105

 

Dockerfile의 각 라인이 하나의 Step이 되며, 각 Step마다 여러 색깔로 표기한 IMAGE ID가 생성되는 것을 확인할 수 있다. Step 1/5 를 보면, ubuntu:16.04를 받아야 하는데, 이미 보유하고 있으므로 다운받지 않는다. 또한 출력되는 IMAGE ID는 005d2078bdfa인데, 이 코드는 docker images의 결과로 나왔던 ubuntu 16.04 버전과 동일한 ID이다. 따라서 Dockerfile을 build할 때는 원래 있는 이미지는 재사용하는 것을 알 수 있다.

 

도커 이미지뿐만 아니라 위 1~5 Step의 모든 항목들은 이미지화 되며, 이러한 이미지들을 저장해 두었다가 다른 Dockerfile에서 동일한 내용을 사용할 때 이미지를 재사용 하는 것이다. 이렇게 모아져서 만들어진 최종 이미지인 dockerfile_ubuntu-nginx 는 005d2078bdfa, 3d241e1c26f6, 90f723b65664, d62272ebb369, c6dca2667105 이미지들이 layer로 겹져쳐서 생성되는 것이다.

dockerfile을 build할 때는, 각 항목을 실행하고 컨테이너를 만들고 컨테이너를 이미지화하고 컨테이너를 삭제하는 일련의 작업을 반복한다. 그래서 위처럼 이미지가 생성되는 것이다. 그런데 dockerfile을 build 할 때 실패하거나 중단하는 경우, docker images나 docker container ls에 이상한 것들이 있을 수 있다. 이것들은 위의 컨테이너 생성, 이미지화, 삭제 등의 일련의 진행 중 취소나 중단이 되었기 때문에 생기는 것이다. 이런것들은 따로 삭제해주면 된다.

 

# 참고 : 도커파일의 레이어 이미지 (중간이미지) 개수를 줄이기

- 여러가지 방법이 있는데, 대표적으로 RUN 명령이 여러개라면 하나로 합칠 수 있다.

- 예를들어, yum -y install httpd , yum -y install php 이렇게 2개라면, yum -y install httpd php  이렇게 합친다.

- 이런식으로 명령어들을 제작자가 입맛에 맞춰 만들 수 있다. && 같은 다중 명령어 등도 사용할 수 있다.

 

+ Recent posts