Docker - 이미지 빌드: Dockerfile 작성 및 실행

Dockerfile 소개

Docker Hub에는 직접 사용 가능한 서비스 이미지, 언어 애플리케이션 이미지, 기본 운영체제 이미지 등 고품질의 공식 이미지가 다수 제공되어 대부분의 요구사항을 충족합니다. 또한, 실제 사용 환경에 맞는 특정 요구사항을 충족하기 위해 사용자 정의 이미지를 생성할 수도 있습니다.

사용자 정의 이미지는 기본적으로 기존 이미지를 기반으로 각 레이어의 구성과 파일을 맞춤 설정하는 과정입니다. 기존 이미지를 기반 이미지로 선택할 수도 있고, scratch 이미지(실제로 존재하지 않는 가상 개념으로, 빈 이미지를 의미)를 선택할 수도 있습니다.

Dockerfile은 새로운 이미지 생성 과정에서 각 레이어의 수정, 설치, 빌드, 작업 명령을 포함하는 텍스트 형식의 스크립트입니다. 각 명령어(Instruction)는 한 레이어를 구축하며, 해당 레이어가 어떻게 구축되어야 하는지를 설명합니다. 빌드 속도를 높이고 Union FS의 최대 레이어 수 제한을 준수하기 위해, 하나의 RUN 명령어 내에서 &&를 사용하여 여러 명령을 연결하여 여러 레이어를 단일 레이어로 단순화할 수 있습니다. Dockerfile은 \를 사용한 줄 바꿈 방식과 행 시작 부분의 # 주석 형식을 지원합니다.

이미지는 다층 저장 방식이며, 각 레이어의 내용은 다음 레이어에서 삭제되지 않고 이미지와 함께 유지됩니다. 따라서 이미지 빌드 시, 각 레이어에 실제 필요한 내용만 추가하고 관련 없는 파일 및 설정은 모두 정리해야 합니다. 좋은 명령어 형식은 유지보수 및 문제 해결을 더욱 간편하게 만듭니다.

Dockerfile의 주요 명령어

Dockerfile의 명령어는 docker build 명령어를 통해 실행됩니다. 더 자세한 정보는 다음을 참고하세요:

빌드 시 사용 명령어

- ADD	        로컬 또는 원격 파일 및 디렉터리 추가. 로컬 리소스를 이미지의 대상 위치에 추가
- ARG	        빌드 시 변수 사용. --build-arg를 통해 매개변수 지정 가능
- COPY	        파일 및 디렉터리 복사
- FROM	        기본 이미지에서 새 빌드 단계 생성. 기존 이미지로부터 생성
- LABEL	        이미지에 메타데이터 추가.
- MAINTAINER	이미지 작성자 지정 (이름과 이메일 주소)
- ONBUILD	    이미지가 빌드에 사용될 때 실행할 명령 지정.
- RUN	        빌드 명령 실행. 셸 명령 실행
- SHELL	        이미지의 기본 셸 설정.
- USER	    사용자 및 그룹 ID 설정.
- WORKDIR	작업 디렉터리 변경.

실행 시 사용 명령어

- CMD	        컨테이너 시작 시 기본 명령 지정. 덮어쓸 수 있으며, 마지막 CMD만 유효
- ENTRYPOINT	컨테이너 시작 시 실행할 내용 지정. 컨테이너 진입점, 덮어쓸 수 없음
- ENV	        환경 변수 설정.
- EXPOSE	    애플리케이션이 수신 대기하는 포트 지정 (호스트에 포트 노출)
- HEALTHCHECK	컨테이너 시작 시 건강 상태 확인.
- VOLUME	    볼륨 마운트 생성. 지정된 경로를 저장소 볼륨으로 마운트
- STOPSIGNAL	컨테이너 종료 시 사용할 시스템 호출 신호 지정.

docker build

Dockerfile에서 이미지 빌드
사용법:	docker build [옵션] PATH | URL | -

이미지 빌드 단계

  1. 이미지 템플릿 결정
  2. Dockerfile 파일 생성
  3. Dockerfile 명령어를 사용하여 Dockerfile 내용 완성
  4. Dockerfile 파일이 있는 경로에서 docker build -t imageName:tag . 실행
  5. docker run 명령어를 실행하고 imageName:tag 및 관련 매개변수 지정

주의사항

  1. PATH 매개변수를 사용하여 컨텍스트 디렉터리를 반드시 지정해야 합니다. Docker는 C/S 구조이므로 docker build 명령은 로컬에서가 아닌 서버 측(Docker 엔진)에서 빌드됩니다. 이미지 빌드 시, 컨텍스트 디렉터리를 지정하는 방식을 통해 서버 측이 로컬 파일을 얻을 수 있어 로컬 파일을 포함하는 이미지를 빌드할 수 있습니다. 간단히 말해, 이미지에 포함되어야 할 로컬 파일은 반드시 컨텍스트 디렉터리에 존재해야 합니다. docker build 명령은 사용자가 지정한 컨텍스트 디렉터리의 내용을 패키징하여 Docker 엔진에 업로드합니다. Docker 엔진은 이를 수신하고 압축을 풀어 이미지 빌드에 필요한 로컬 파일을 얻습니다.
  2. 컨텍스트 디렉터리에서 .dockerignore (.gitignore와 유사한 구문)를 사용하여 이미지에 포함되지 않아야 할 내용을 제외할 수 있습니다.
  3. COPY, ADD 등 명령어의 소스 파일 경로는 컨텍스트(PATH) 디렉터리의 상대 경로를 사용합니다.
  4. Dockerfile을 지정하지 않으면, Docker는 기본적으로 컨텍스트 디렉터리에 Dockerfile이라는 이름의 파일을 찾습니다.

기타 사용법

  • URL에서 빌드
  • 제공된 tar 압축 파일로 빌드: Docker 엔진이 압축 파일을 다운로드하고 자동으로 압축을 풀어 컨텍스트로 빌드 시작.
  • 표준 입력에서 Dockerfile을 읽어 빌드 (컨텍스트 없음, COPY 등 명령어 실행 불가): docker build - < Dockerfile 또는 cat Dockerfile | docker build -
  • 표준 입력에서 컨텍스트 압축 파일을 읽어 빌드: docker build - < context.tar.gz
  • FROM scratch는 빈 이미지를 기본 이미지로 선택하며, 작성된 명령어가 이미지의 첫 번째 레이어로 존재하기 시작합니다. Linux에서 정적 컴파일된 프로그램에 적합하며, 이미지 크기를 더 작게 만듭니다.

Dockerfile 작성 및 실행 예제

Dockerfile 작성

[root@CentOS7 docker]# pwd
/tmp/docker
[root@CentOS7 docker]# ls -l
총 0
drwxr-xr-x 2 root root 24 5월   8 23:52 data
drwxr-xr-x 3 root root 60 5월   9 00:13 test
[root@CentOS7 docker]# tree
.
├── data
│   └── sample.txt
└── test
    ├── aliyun-sources.txt
    ├── buildfile
    └── dir
        └── messages.txt

3개의 디렉터리, 4개의 파일
[root@CentOS7 docker]# 
[root@CentOS7 docker]# cat /tmp/docker/data/sample.txt 
1234567890
[root@CentOS7 docker]# 
[root@CentOS7 docker]# cat /tmp/docker/test/aliyun-sources.txt 
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
[root@CentOS7 docker]# 
[root@CentOS7 docker]# cat /tmp/docker/test/buildfile
# 이것은 Docker 빌드의 예시입니다. 
FROM ubuntu
MAINTAINER anliven "anliven@yeah.net"
RUN echo 'Run docker build - create file!' > /tmp/file-create.log
COPY aliyun-sources.txt /etc/apt/sources.list
COPY dir/messages.txt /tmp/file-copy.log
VOLUME /tmp/docker/data
# ENV http_proxy="http://10.144.1.10:8080"
RUN apt-get update \
    && apt-get install -y inetutils-ping iproute net-tools \
    && apt-get install -y vim \
    && apt-get purge -y --auto-remove
[root@CentOS7 docker]# 
[root@CentOS7 docker]# cat /tmp/docker/test/dir/messages.txt 
Run docker build - copy file!
[root@CentOS7 docker]# 

사용자 정의 이미지 빌드

[root@CentOS7 ~]# docker build --file /tmp/docker/test/buildfile --tag ubuntu:test /tmp/docker/test/
컨텍스트를 Docker 데몬에 전송 중  5.12 kB
단계 1/7 : FROM ubuntu
 ---> f7b3f317ec73
단계 2/7 : MAINTAINER anliven <anliven@yeah.net>
 ---> Running in 7c1140a0cc72
 ---> 9a0fb45df847
중간 컨테이너 7c1140a0cc72 제거
단계 3/7 : RUN echo 'Run docker build - create file!' > /tmp/file-create.log
 ---> Running in 33bb7a725234
 ---> 866235e56f75
중간 컨테이너 33bb7a725234 제거
단계 4/7 : COPY aliyun-sources.txt /etc/apt/sources.list
 ---> 6de0504452f5
중간 컨테이너 e98687ed3e37 제거
단계 5/7 : COPY dir/messages.txt /tmp/file-copy.log
 ---> 8def1507d4f3
중간 컨테이너 66e68d3efc2d 제거
단계 6/7 : VOLUME /tmp/docker/data
 ---> Running in 10cca5bef10e
 ---> 6e887fff9079
중간 컨테이너 10cca5bef10e 제거
단계 7/7 : RUN apt-get update     && apt-get install -y inetutils-ping iproute net-tools     && apt-get install -y vim     && apt-get purge -y --auto-remove
 ---> Running in 4c54d21066cd
Get:1 http://mirrors.aliyun.com/ubuntu xenial InRelease [247 kB]
Get:2 http://mirrors.aliyun.com/ubuntu xenial-updates InRelease [102 kB]
Get:3 http://mirrors.aliyun.com/ubuntu xenial-backports InRelease [102 kB]
......
......
......
Processing triggers for libc-bin (2.23-0ubuntu7) ...
Reading package lists...
Building dependency tree...
Reading state information...
0 upgraded, 0 newly installed, 0 to remove and 9 not upgraded.
 ---> 62b945705a30
중간 컨테이너 4c54d21066cd 제거
이미지 성공적으로 빌드됨 (ID: 62b945705a30)
[root@CentOS7 ~]# 

검증

[root@CentOS7 ~]# docker images ubuntu
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
ubuntu              test                62b945705a30        약 1분 전             202.1 MB
docker.io/ubuntu    latest              f7b3f317ec73        13일 전              117.3 MB
[root@CentOS7 ~]# 
[root@CentOS7 ~]# docker inspect --format "{{ .Config.Volumes }}" ubuntu:test
map[/tmp/docker/data:{}]
[root@CentOS7 ~]# 
[root@CentOS7 ~]# docker history ubuntu:test
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
62b945705a30        5분 전              /bin/sh -c apt-get update     && apt-get inst   84.85 MB            
6e887fff9079        6분 전              /bin/sh -c #(nop)  VOLUME [/tmp/docker/data]    0 B                 
8def1507d4f3        6분 전              /bin/sh -c #(nop) COPY file:45739c777f02cabe8   30 B                
6de0504452f5        6분 전              /bin/sh -c #(nop) COPY file:3d19f8187c6e93e48   655 B               
866235e56f75        6분 전              /bin/sh -c echo 'Run docker build - create fi   32 B                
9a0fb45df847        6분 전              /bin/sh -c #(nop)  MAINTAINER anliven <anlive   0 B                 
f7b3f317ec73        13일 전             /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>           13일 전             /bin/sh -c mkdir -p /run/systemd && echo 'doc   7 B                 
<missing>           13일 전             /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/   2.759 kB            
<missing>           13일 전             /bin/sh -c rm -rf /var/lib/apt/lists/*          0 B                 
<missing>           13일 전             /bin/sh -c set -xe   && echo '#!/bin/sh' > /u   745 B               
<missing>           13일 전             /bin/sh -c #(nop) ADD file:141408db9037263a47   117.3 MB            
[root@CentOS7 ~]# 
[root@CentOS7 ~]# docker run -it ubuntu:test
root@702e453e458f:/#   
root@702e453e458f:/# ls -l /tmp
총 8
drwxr-xr-x 3 root root 18 5월  8 16:33 docker
-rw-r--r-- 1 root root 30 5월  8 15:53 file-copy.log
-rw-r--r-- 1 root root 32 5월  8 16:33 file-create.log
root@702e453e458f:/# 
root@702e453e458f:/# cat /tmp/file-copy.log 
Run docker build - copy file!
root@702e453e458f:/# cat /tmp/file-create.log 
Run docker build - create file!
root@702e453e458f:/# 
root@702e453e458f:/# ls -l /tmp/docker/
총 0
drwxr-xr-x 2 root root 6 5월  8 16:40 data
root@702e453e458f:/# ls -l /tmp/docker/data/
총 0
root@702e453e458f:/# 
root@702e453e458f:/# dpkg --list inetutils-ping |grep ii
ii  inetutils-ping 2:1.9.4-1build1 amd64        ICMP echo tool
root@702e453e458f:/# 
root@702e453e458f:/# dpkg --list iproute |grep ii
ii  iproute        1:4.3.0-1ubuntu3 all          transitional dummy package for iproute2
root@702e453e458f:/# 
root@702e453e458f:/# dpkg --list net-tools |grep ii
ii  net-tools      1.60-26ubuntu1 amd64        NET-3 networking toolkit
root@702e453e458f:/# 
root@702e453e458f:/# exit
[root@CentOS7 ~]# 

참고 정보

태그: docker Dockerfile container image Build

7월 29일 11:01에 게시됨