Dockerfile 소개
Docker Hub에는 직접 사용 가능한 서비스 이미지, 언어 애플리케이션 이미지, 기본 운영체제 이미지 등 고품질의 공식 이미지가 다수 제공되어 대부분의 요구사항을 충족합니다. 또한, 실제 사용 환경에 맞는 특정 요구사항을 충족하기 위해 사용자 정의 이미지를 생성할 수도 있습니다.
사용자 정의 이미지는 기본적으로 기존 이미지를 기반으로 각 레이어의 구성과 파일을 맞춤 설정하는 과정입니다. 기존 이미지를 기반 이미지로 선택할 수도 있고, scratch 이미지(실제로 존재하지 않는 가상 개념으로, 빈 이미지를 의미)를 선택할 수도 있습니다.
Dockerfile은 새로운 이미지 생성 과정에서 각 레이어의 수정, 설치, 빌드, 작업 명령을 포함하는 텍스트 형식의 스크립트입니다.
각 명령어(Instruction)는 한 레이어를 구축하며, 해당 레이어가 어떻게 구축되어야 하는지를 설명합니다.
빌드 속도를 높이고 Union FS의 최대 레이어 수 제한을 준수하기 위해, 하나의 RUN 명령어 내에서 &&를 사용하여 여러 명령을 연결하여 여러 레이어를 단일 레이어로 단순화할 수 있습니다.
Dockerfile은 \를 사용한 줄 바꿈 방식과 행 시작 부분의 # 주석 형식을 지원합니다.
이미지는 다층 저장 방식이며, 각 레이어의 내용은 다음 레이어에서 삭제되지 않고 이미지와 함께 유지됩니다. 따라서 이미지 빌드 시, 각 레이어에 실제 필요한 내용만 추가하고 관련 없는 파일 및 설정은 모두 정리해야 합니다. 좋은 명령어 형식은 유지보수 및 문제 해결을 더욱 간편하게 만듭니다.
Dockerfile의 주요 명령어
Dockerfile의 명령어는 docker build 명령어를 통해 실행됩니다.
더 자세한 정보는 다음을 참고하세요:
- https://docs.docker.com/reference/dockerfile/
- https://docs.docker.com/build/concepts/dockerfile/
- https://docs.docker.com/engine/reference/builder/
빌드 시 사용 명령어
- 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 | -
이미지 빌드 단계
- 이미지 템플릿 결정
- Dockerfile 파일 생성
- Dockerfile 명령어를 사용하여 Dockerfile 내용 완성
- Dockerfile 파일이 있는 경로에서
docker build -t imageName:tag .실행 docker run명령어를 실행하고imageName:tag및 관련 매개변수 지정
주의사항
PATH매개변수를 사용하여 컨텍스트 디렉터리를 반드시 지정해야 합니다. Docker는 C/S 구조이므로docker build명령은 로컬에서가 아닌 서버 측(Docker 엔진)에서 빌드됩니다. 이미지 빌드 시, 컨텍스트 디렉터리를 지정하는 방식을 통해 서버 측이 로컬 파일을 얻을 수 있어 로컬 파일을 포함하는 이미지를 빌드할 수 있습니다. 간단히 말해, 이미지에 포함되어야 할 로컬 파일은 반드시 컨텍스트 디렉터리에 존재해야 합니다.docker build명령은 사용자가 지정한 컨텍스트 디렉터리의 내용을 패키징하여 Docker 엔진에 업로드합니다. Docker 엔진은 이를 수신하고 압축을 풀어 이미지 빌드에 필요한 로컬 파일을 얻습니다.- 컨텍스트 디렉터리에서
.dockerignore(.gitignore와 유사한 구문)를 사용하여 이미지에 포함되지 않아야 할 내용을 제외할 수 있습니다. - COPY, ADD 등 명령어의 소스 파일 경로는 컨텍스트(PATH) 디렉터리의 상대 경로를 사용합니다.
- 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 ~]#