[번역]Dockerfile 레퍼런스 #3 정보
[번역]Dockerfile 레퍼런스 #3관련링크
본문
ENTRYPOINT
ENTRYPOINT
는 두 가지 형태가 있습니다:
ENTRYPOINT ["executable", "param1", "param2"]
(exec form, preferred)ENTRYPOINT command param1 param2
(shell form)
ENTRYPOINT
를 사용하면 실행 파일로 실행될 컨테이너를 구성 할 수 있습니다.
예를 들어, 다음은 기본 컨텐츠로 nginx
를 시작하고 포트 80 에서 수신합니다.
docker run -i -t --rm -p 80:80 nginx
docker run
에 대한 명령 행 인수는 exec 형식 ENTRYPOINT
의 모든 요소 뒤에 추가되며 CMD
를 사용하여 지정된 모든 요소를 대체합니다. 이를 통해 인수가 진입점으로 전달될 수 있습니다. 즉, docker run -d
는 -d
인수를 진입점으로 전달합니다. docker run --entrypoint
플래그를 사용하여 ENTRYPOINT
명령을 무시할 수 있습니다.
shell 형식은 CMD
또는run
명령행 인수가 사용되는 것을 방지하지만, ENTRYPOINT
가 신호를 전달하지 않는 /bin/sh -c
의 하위 명령으로 시작된다는 단점이 있습니다. 즉, 실행 파일은 컨테이너의 'PID 1'이 아니며 Unix 신호를 수신하지 않습니다. 따라서 실행 파일은docker stop
에서 'SIGTERM'을 수신하지 않습니다.
Dockerfile
의 마지막 ENTRYPOINT
명령만 적용됩니다.
Exec form ENTRYPOINT example
ENTRYPOINT
의 exec 형식을 사용하여 상당히 안정적인 기본 명령 및 인수를 설정 한 다음 CMD
형식을 사용하여 변경될 가능성이 높은 추가 기본값을 설정할 수 있습니다.
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
컨테이너를 실행하면 top 이 유일한 프로세스임을 알 수 있습니다.
$ docker run -it --rm --name test top -H
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
결과를 더 자세히 조사하려면 docker exec
를 사용할 수 있습니다.
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
그리고 docker stop test
를 사용하여 top
을 정상적으로 종료하도록 요청할 수 있습니다.
다음 Dockerfile
은 ENTRYPOINT
를 사용하여 포 그라운드에서 Apache 를 실행하는 것을 보여줍니다 (즉, PID 1
).
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
단일 실행 파일에 대한 시작 스크립트를 작성해야하는 경우 exec
및 gosu
명령을 사용하여 최종 실행 파일이 Unix 신호를 수신하도록 할 수 있습니다.
#!/usr/bin/env bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"
마지막으로 종료시 추가 정리 (또는 다른 컨테이너와 통신)가 필요하거나 둘 이상의 실행 파일을 조정해야하는 경우 ENTRYPOINT
스크립트가 Unix 신호를 수신하고 전달한 다음 확인해야합니다. 더 많은 작업을 수행합니다.
#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too
# USE the trap if you need to also do manual cleanup after the service is stopped,
# or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM
# start service in background here
/usr/sbin/apachectl start
echo "[hit enter key to exit] or run 'docker stop '"
read
# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop
echo "exited $0"
docker run -it --rm -p 80:80 --name test apache
로 이 이미지를 실행하면 docker exec
또는 docker top
을 사용하여 컨테이너 프로세스를 검사한 다음 스크립트에서 Apache 중지를 요청할 수 있습니다.
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
$ docker top test
PID USER COMMAND
10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2
10054 root /usr/sbin/apache2 -k start
10055 33 /usr/sbin/apache2 -k start
10056 33 /usr/sbin/apache2 -k start
$ /usr/bin/time docker stop test
test
real 0m 0.27s
user 0m 0.03s
sys 0m 0.03s
참고:
--entrypoint
를 사용하여ENTRYPOINT
설정을 무시할 수 있지만 바이너리는 exec로만 설정할 수 있습니다 (sh -c
는 사용되지 않음).
참고 : exec 형식은 JSON 배열로 구문 분석되므로 작은 따옴표 (“)가 아닌 단어 주위에 큰 따옴표 (“)를 사용해야 합니다.
참고: shell 양식과 달리 exec 양식은 명령 쉘을 호출하지 않습니다. 이는 정상적인 쉘 처리가 발생하지 않음을 의미합니다. 예를 들어,
ENTRYPOINT [ "echo", "$HOME"]
는$HOME
에서 변수 대체를 수행하지 않습니다. 쉘 처리를 원한다면 shell 양식을 사용하거나 직접 쉘을 실행하십시오 (예:ENTRYPOINT [ "sh", "-c", "echo $HOME"]
). 쉘 양식의 경우와 같이 exec 양식을 사용하고 쉘을 직접 실행하는 경우도 도커가 아닌 환경 변수 확장을 수행하는 쉘입니다.
Shell form ENTRYPOINT example
ENTRYPOINT
에 일반 문자열을 지정할 수 있으며 /bin/sh -c
에서 실행됩니다. 이 형식은 쉘 처리를 사용하여 쉘 환경 변수를 대체하며 CMD
또는 docker run
명령 행 인수를 무시합니다. docker stop
이 오랫동안 실행중인 ENTRYPOINT
실행 파일을 올바르게 신호하도록하려면 exec로 시작해야 합니다.
FROM ubuntu
ENTRYPOINT exec top -b
이 이미지를 실행하면 단일 PID 1
프로세스가 표시됩니다.
$ docker run -it --rm --name test top
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
Load average: 0.08 0.03 0.05 2/98 6
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root R 3164 0% 0% top -b
docker stop
에서 깨끗하게 종료됩니다.
$ /usr/bin/time docker stop test
test
real 0m 0.20s
user 0m 0.02s
sys 0m 0.04s
ENTRYPOINT
의 시작 부분에 exec
를 추가하지 않은 경우:
FROM ubuntu
ENTRYPOINT top -b
CMD --ignored-param1
그런 다음 실행할 수 있습니다 (다음 단계의 이름 제공).
$ docker run -it --name test top --ignored-param2
Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq
Load average: 0.01 0.02 0.05 2/101 7
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2
7 1 root R 3164 0% 0% top -b
top
의 출력에서 지정된 ENTRYPOINT
가 PID 1
이 아님을 알 수 있습니다.
docker stop test
를 실행하면 컨테이너가 깨끗하게 종료되지 않습니다. 시간 초과 후 stop
명령이 SIGKILL
을 보내도록 강제 실행됩니다.
$ docker exec -it test ps aux
PID USER COMMAND
1 root /bin/sh -c top -b cmd cmd2
7 root top -b
8 root ps aux
$ /usr/bin/time docker stop test
test
real 0m 10.19s
user 0m 0.04s
sys 0m 0.03s
Understand how CMD and ENTRYPOINT interact
CMD
및 ENTRYPOINT
명령은 컨테이너를 실행할 때 어떤 명령이 실행 될지 정의합니다. 그들의 협력을 설명하는 규칙은 거의 없습니다.
-
Dockerfile
은CMD
또는ENTRYPOINT
명령 중 하나 이상을 지정해야합니다. -
ENTRYPOINT
는 컨테이너를 실행 파일로 사용할 때 정의해야합니다. -
ENTRYPOINT
명령의 기본 인수를 정의하거나 컨테이너에서 임시 명령을 실행하는 방법으로CMD
를 사용해야합니다. -
컨테이너를 대체 인수로 실행하면
CMD
가 재정의됩니다.
아래 표는 다른 ENTRYPOINT
/CMD
조합에 대해 실행되는 명령을 보여줍니다.
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
참고: 기본 이미지에서
CMD
를 정의한 경우,ENTRYPOINT
를 설정하면CMD
가 빈 값으로 재설정됩니다. 이 시나리오에서는 현재 이미지에CMD
가 정의되어 있어야 합니다.
VOLUME
VOLUME ["/data"]
VOLUME
명령어는 지정된 이름으로 마운트 포인트를 생성하고 네이티브 호스트 또는 다른 컨테이너에서 외부 마운트된 볼륨을 보유하는 것으로 표시합니다. 값은 JSON 배열, VOLUME ["/var/log/"]
또는 여러 인수가있는 일반 문자열 (예: VOLUME /var/log
또는 VOLUME /var/log /var/db
) 일 수 있습니다. Docker 클라이언트를 통한 자세한 정보 / 예 및 마운트 지침은 볼륨을 통한 디렉토리 공유 설명서를 참조하십시오.
docker run
명령은 기본 이미지 내 지정된 위치에 존재하는 데이터로 새로 생성 된 볼륨을 초기화합니다. 예를 들어 다음 Dockerfile
스니펫을 고려하십시오.
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
이 Dockerfile 은 docker run
이 /myvol
에 새 마운트 지점을 만들고 인사말 파일을 새로 만든 볼륨에 복사하는 이미지를 생성합니다.
Notes about specifying volumes
Dockerfile
의 볼륨에 대해 다음 사항을 명심하십시오.
-
Windows 기반 컨테이너의 볼륨: Windows 기반 컨테이너를 사용할 때 컨테이너 내부의 볼륨 대상은 다음 중 하나여야 합니다.
- 존재하지 않거나 비어있는 디렉토리
C:
이외의 드라이브
-
Dockerfile 내에서 볼륨 변경: 빌드 단계에서 볼륨이 선언된 후 볼륨 내에서 데이터를 변경하면 해당 변경 사항이 삭제됩니다.
-
JSON 형식: 목록이 JSON 배열로 구문 분석됩니다. 단어를 작은 따옴표 (
'
)가 아닌 큰 따옴표 ("
)로 묶어야합니다. -
호스트 디렉토리는 컨테이너 런타임에 선언됩니다: 호스트 디렉토리 (마운트 포인트)는 본질적으로 호스트에 따라 다릅니다. 특정 호스트 디렉토리를 모든 호스트에서 사용할 수 있다고 보장할 수 없기 때문에 이미지 이식성을 유지합니다. 이러한 이유로 Dockerfile 내에서 호스트 디렉토리를 마운트할 수 없습니다.
VOLUME
명령은host-dir
매개 변수 지정을 지원하지 않습니다. 컨테이너를 만들거나 실행할 때 마운트 지점을 지정해야합니다.
USER
USER [:] or
USER [:]
USER
명령어는 사용자 이름 (또는 UID)과 선택적으로 사용자 그룹 (또는 GID)을 설정하여 이미지를 실행할 때 그리고 Dockerfile
에서 그 뒤에 오는 RUN
, CMD
및 ENTRYPOINT
명령에 사용합니다.
경고: 사용자에게 기본 그룹이 없으면
root
그룹으로 이미지 (또는 다음 지침)가 실행됩니다.
Windows 에서 사용자는 기본 제공 계정이 아닌 경우 먼저 작성해야합니다. 이것은 Dockerfile 의 일부로 불리는
net user
명령으로 수행 할 수 있습니다.
FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrick
WORKDIR
WORKDIR /path/to/workdir
WORKDIR
명령어는 Dockerfile
에서 RUN
, CMD
, ENTRYPOINT
, COPY
및 ADD
명령어에 대한 작업 디렉토리를 설정합니다. WORKDIR
이 존재하지 않으면, 이후의 Dockerfile
명령에서 사용되지 않더라도 생성됩니다.
WORKDIR
명령어는 Dockerfile
에서 여러 번 사용될 수 있습니다. 상대 경로가 제공되면 이전 WORKDIR
명령의 경로에 상대적인 경로가됩니다. 예를 들면 다음과 같습니다.
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
이 Dockerfile
에서 마지막 pwd
명령의 출력은 /a/b/c
입니다.
WORKDIR
명령어는 ENV
를 사용하여 이전에 설정한 환경 변수를 해결할 수 있습니다. Dockerfile
에 명시적으로 설정된 환경 변수만 사용할 수 있습니다. 예를 들면 다음과 같습니다.
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
이 Dockerfile
의 마지막 pwd
명령 출력은 /path/$DIRNAME
입니다.
ARG
ARG [=]
ARG
명령어는 사용자가 --build-arg =
플래그를 사용하여 docker build
명령으로 빌드시 빌더에 전달할 수있는 변수를 정의합니다. 사용자가 Dockerfile 에 정의되지 않은 빌드 인수를 지정하면 빌드가 경고를 출력합니다.
[Warning] One or more build-args [foo] were not consumed.
Dockerfile 은 하나 이상의 ARG
명령을 포함 할 수 있습니다. 예를 들어, 다음은 유효한 Dockerfile 입니다.
FROM busybox
ARG user1
ARG buildno
...
경고: GitHub 키, 사용자 자격 증명 등과 같은 비밀을 전달하기 위해 빌드 타임 변수를 사용하지 않는 것이 좋습니다. 빌드 타임 변수 값은
docker history
명령으로 이미지의 모든 사용자에게 표시됩니다.
Default values
ARG
명령어는 선택적으로 기본값을 포함 할 수 있습니다:
FROM busybox
ARG user1=someuser
ARG buildno=1
...
ARG
명령어의 기본값이 있고 빌드시 전달된 값이 없는 경우 빌더는 기본값을 사용합니다.
Scope
ARG
변수 정의는 명령 줄이나 다른 곳에서 인수를 사용하는 것이 아니라 `Dockerfile '에 정의된 행에서 적용됩니다. 예를 들어,이 Dockerfile 을 고려하십시오.
1 FROM busybox
2 USER ${user:-some_user}
3 ARG user
4 USER $user
...
사용자는 다음을 호출하여이 파일을 빌드합니다.
$ docker build --build-arg user=what_user .
user
변수가 다음 3 행에 정의되어 있으므로 2 행의USER
는 some_user
로 평가됩니다. 명령 행에 전달되었습니다. ARG
명령어로 정의하기 전에 변수를 사용하면 빈 문자열이 됩니다.
ARG
명령어는 정의된 빌드 단계의 끝에서 범위를 벗어납니다. 여러 단계에서 arg 를 사용하려면 각 단계에는 ARG
명령이 포함되어야 합니다.
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
FROM busybox
ARG SETTINGS
RUN ./run/other $SETTINGS
Using ARG variables
ARG
또는 ENV
명령어를 사용하여 RUN
명령어에 사용 가능한 변수를 지정할 수 있습니다. ENV
명령어를 사용하여 정의된 환경 변수는 항상 같은 이름의 ARG
명령어를 재정의합니다. ENV
및 ARG
명령이 있는 이 Dockerfile 을 고려하십시오.
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER v1.0.0
4 RUN echo $CONT_IMG_VER
그런 다음이 이미지가 다음 명령으로 빌드되었다고 가정하십시오.
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .
이 경우 RUN
명령어는 user:v2.0.1
이 전달한 ARG
설정 대신 v1.0.0
을 사용합니다. 이 동작은 로컬 범위 변수가 정의 지점에서 인수로 전달되거나 환경에서 상속 된 변수를 재정의하는 쉘 스크립트와 유사합니다.
위의 예를 사용하지만 다른 ENV
사양을 사용하면 ARG
와 ENV
명령어 사이에보다 유용한 상호 작용을 만들 수 있습니다.
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
4 RUN echo $CONT_IMG_VER
ARG
명령어와 달리 ENV
값은 항상 빌드된 이미지에서 유지됩니다. --build-arg
플래그가 없는 도커 빌드를 고려하십시오.
$ docker build .
이 Dockerfile 예제를 사용하면 'CONT_IMG_VER'는 이미지에서 계속 유지되지만 'ENV'명령에 의해 3 행에서 기본값으로 설정되므로 값은 'v1.0.0'입니다.
이 예제의 변수 확장 기술을 사용하면 명령 줄에서 인수를 전달하고 ENV
명령을 사용하여 최종 이미지에서 인수를 유지할 수 있습니다. 변수 확장은 제한된 Dockerfile 명령어 세트에 대해서만 지원됩니다.
Predefined ARGs
Docker 에는 Dockerfile 의 해당 ARG
명령없이 사용할 수 있는 사전 정의된 ARG
변수 세트가 있습니다.
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
이를 사용하려면 플래그를 사용하여 명령 행에 전달하십시오.
--build-arg =
기본적으로 이러한 사전 정의된 변수는 'docker history'의 출력에서 제외됩니다. 이를 제외하면 HTTP_PROXY
변수에서 민감한 인증 정보가 실수로 유출될 위험이 줄어 듭니다.
예를 들어 --build-arg HTTP_PROXY=http://user:*** 개인정보보호를 위한 이메일주소 노출방지 ***
을 사용하여 다음 Dockerfile 을 빌드하는 것이 좋습니다.
FROM ubuntu
RUN echo "Hello World"
이 경우,HTTP_PROXY
변수의 값은 docker history
에서 사용할 수 없으며 캐시되지 않습니다. 위치를 변경하고 프록시 서버가 http://user:*** 개인정보보호를 위한 이메일주소 노출방지 ***
으로 변경된 경우 후속 빌드로 인해 캐시 누락이 발생하지 않습니다.
이 동작을 무시해야하는 경우 Dockerfile 에 다음과 같이 ARG
문을 추가하면 됩니다.
FROM ubuntu
ARG HTTP_PROXY
RUN echo "Hello World"
이 Dockerfile 을 빌드 할 때 HTTP_PROXY
는 docker history
에 유지되며 값을 변경하면 빌드 캐시가 무효화됩니다.
Automatic platform ARGs in the global scope
이 기능은 BuildKit 백엔드를 사용하는 경우에만 사용할 수 있습니다.
Docker 는 빌드를 수행하는 노드의 플랫폼 (빌드 플랫폼)과 결과 이미지의 플랫폼 (타겟 플랫폼)에 대한 정보로 일련의 ARG
변수를 미리 정의합니다. 타겟 플랫폼은 docker build
에서 --platform
플래그로 지정할 수 있습니다.
다음의 ARG
변수가 자동으로 설정됩니다.
TARGETPLATFORM
- platform of the build result. Eglinux/amd64
,linux/arm/v7
,windows/amd64
.TARGETOS
- OS component of TARGETPLATFORMTARGETARCH
- architecture component of TARGETPLATFORMTARGETVARIANT
- variant component of TARGETPLATFORMBUILDPLATFORM
- platform of the node performing the build.BUILDOS
- OS component of BUILDPLATFORMBUILDARCH
- architecture component of BUILDPLATFORMBUILDVARIANT
- variant component of BUILDPLATFORM
이 인수는 전역 범위에서 정의되므로 빌드 단계 또는 RUN
명령에서 자동으로 사용할 수 없습니다. 빌드 단계에서 이러한 인수 중 하나를 표시하려면 값 없이 다시 정의하십시오.
예를 들면 다음과 같습니다.
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"
Impact on build caching
ARG
변수는 'ENV'변수와 같이 빌드된 이미지에 유지되지 않습니다. 그러나 ARG
변수는 비슷한 방식으로 빌드 캐시에 영향을줍니다. Dockerfile 이 값이 이전 빌드와 다른 ARG
변수를 정의하는 경우 정의가 아니라 처음 사용시 "캐시 누락"이 발생합니다. 특히, ARG
명령어 다음에 나오는 모든 RUN
명령어는 ARG
변수를 내재적으로 (환경 변수로) 사용하므로 캐시 누락이 발생할 수 있습니다. Dockerfile
에 일치하는ARG
문이 없으면 모든 사전 정의 된 ARG
변수는 캐싱에서 제외됩니다.
예를 들어 다음 두 Dockerfile 을 고려하십시오.
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 RUN echo $CONT_IMG_VER
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 RUN echo hello
명령 행에 --build-arg CONT_IMG_VER=
를 지정하면 두 경우 모두 2 행의 스펙으로 인해 캐시 누락이 발생하지 않습니다. ARG CONT_IMG_VER
는 RUN
라인을 CONT_IMG_VER=
echo hello 실행과 동일하게 식별하므로 `` 가 변경되면 캐시 미스가 발생합니다.
동일한 명령 줄에서 다른 예를 고려하십시오.
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER $CONT_IMG_VER
4 RUN echo $CONT_IMG_VER
이 예제에서 캐시 미스는 3 행에서 발생합니다. ENV
의 변수 값이 ARG
변수를 참조하고 해당 변수가 명령 행을 통해 변경되기 때문에 누락이 발생합니다. 이 예에서 ENV
명령은 이미지에 값을 포함시킵니다.
ENV
명령어가 이 Dockerfile 과 같은 동일한 이름의 ARG
명령어를 재정의하는 경우 :
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER hello
4 RUN echo $CONT_IMG_VER
CONT_IMG_VER
의 값이 상수 (hello
)이므로 3 행은 캐시 누락을 유발하지 않습니다. 결과적으로RUN
(라인 4)에 사용된 환경 변수와 값은 빌드간에 변경되지 않습니다.
ONBUILD
ONBUILD [INSTRUCTION]
ONBUILD
명령어는 이미지가 다른 빌드의 기본으로 사용될 때 나중에 실행될 trigger 명령어를 이미지에 추가합니다. 트리거는 다운 스트림 Dockerfile
의 FROM
명령 바로 뒤에 삽입된 것처럼 다운 스트림 빌드 컨텍스트에서 실행됩니다.
모든 빌드 명령은 트리거로 등록 될 수 있습니다.
다른 이미지를 빌드하기 위한 기반으로 사용될 이미지를 빌드할 때 유용합니다 (예: 응용 프로그램 빌드 환경 또는 사용자별 구성으로 사용자 정의할 수 있는 데몬).
예를 들어, 이미지가 재사용 가능한 Python 애플리케이션 빌더인 경우 특정 디렉토리에 애플리케이션 소스 코드를 추가해야 하며 빌드 스크립트를 after라고 해야 합니다. 아직 애플리케이션 소스 코드에 액세스할 수 없기 때문에 지금 ADD
및 RUN
을 호출할 수 없으며 애플리케이션 빌드마다 다릅니다. 응용 프로그램 개발자는 응용 프로그램에 복사하여 붙여 넣을 수 있는 상용구 Dockerfile
을 제공할 수 있지만 비효율적이며 오류가 발생하기 쉽고 응용 프로그램별 코드와 혼합되어 업데이트하기가 어렵습니다.
해결책은 다음 빌드 단계에서 ONBUILD
를 사용하여 나중에 실행할 고급 명령을 등록하는 것입니다.
작동 방식은 다음과 같습니다.
ONBUILD
명령이 발생하면 빌더는 빌드중인 이미지의 메타 데이터에 트리거를 추가합니다. 지침은 현재 빌드에 영향을 미치지 않습니다.- 빌드가 끝나면 모든 트리거 목록이 이미지
OnBuild
아래 이미지 매니페스트에 저장됩니다.docker inspect
명령으로 검사 할 수 있습니다. - 나중에 이미지는
FROM
명령어를 사용하여 새로운 빌드의 기반으로 사용될 수 있습니다.FROM
명령어 처리 과정에서 다운 스트림 빌더는ONBUILD
트리거를 찾아서 등록 된 순서대로 실행합니다. 트리거 중 하나라도 실패하면FROM
명령이 중단되어 빌드가 실패합니다. 모든 트리거가 성공하면FROM
명령이 완료되고 빌드는 평소대로 계속됩니다. - 실행 후 최종 이미지에서 트리거가 지워집니다. 다시 말해, 그들은 "손자"빌드에 의해 상속되지 않습니다.
예를 들어 다음과 같이 추가 할 수 있습니다.
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
경고:
ONBUILD ONBUILD
를 사용한ONBUILD
명령 연결은 허용되지 않습니다.
경고:
ONBUILD
명령은FROM
또는MAINTAINER
명령을 트리거 할 수 없습니다.
STOPSIGNAL
STOPSIGNAL signal
STOPSIGNAL
명령은 컨테이너로 보내질 시스템 호출 신호를 설정합니다. 이 신호는 커널의 syscall 테이블의 위치 (예: 9) 또는 SIGNAME 형식의 신호 이름 (예: SIGKILL)과 일치하는 유효한 부호없는 숫자일 수 있습니다.
HEALTHCHECK
HEALTHCHECK
명령어는 두 가지 형태가 있습니다:
HEALTHCHECK [OPTIONS] CMD command
(컨테이너 내부에서 명령을 실행하여 컨테이너 상태를 확인하십시오)HEALTHCHECK NONE
(기본 이미지에서 상속 된 상태 확인을 비활성화)
HEALTHCHECK
명령은 Docker 에게 컨테이너가 여전히 작동 중인지 테스트하는 방법을 알려줍니다. 이것은 서버 프로세스가 여전히 실행 중이더라도 무한 루프에 갇혀서 새 연결을 처리할 수 없는 웹 서버와 같은 경우를 감지 할 수 있습니다.
컨테이너에 상태 점검이 지정되면, 컨테이너는 정상 상태 외에 상태를 갖습니다. 이 상태는 처음에 starting
입니다. 건강 검진이 통과 될 때마다 healthy
가 됩니다 (이전의 상태). 일정한 수의 연속 실패 후에는 unhealthy
상태가됩니다.
CMD 이전에 나타날 수있는 옵션은 다음과 같습니다.
--interval=DURATION
(default:30s
)--timeout=DURATION
(default:30s
)--start-period=DURATION
(default:0s
)--retries=N
(default:3
)
상태 확인은 컨테이너가 시작된 후 interval초 후에 실행된 다음 이전의 각 확인이 완료된 후 interval초 후에 다시 실행됩니다.
한 번의 검사 실행이 timeout초보다 오래 걸리면 검사가 실패한 것으로 간주됩니다.
컨테이너가 건강에 해로운 것으로 간주 되려면 상태 확인이 retries가 됩니다.
start period은 부트 스트랩에 시간이 필요한 컨테이너의 초기화 시간을 제공합니다. 해당 기간 동안의 프로브 실패는 최대 재시도 횟수에 포함되지 않습니다. 그러나 시작 기간 동안 상태 점검에 성공하면 컨테이너가 시작된 것으로 간주되고 모든 연속 실패는 최대 재시도 횟수로 계산됩니다.
Dockerfile 에는 하나의HEALTHCHECK
명령만 있을 수 있습니다. 둘 이상을 나열하면 마지막 HEALTHCHECK
만 적용됩니다.
CMD
키워드 다음의 명령은 쉘 명령 (예: HEALTHCHECK CMD /bin/check-running
) 또는 exec 배열일 수 있습니다 (다른 Dockerfile 명령과 동일; 자세한 내용은 ENTRYPOINT
참조).
명령의 종료 상태는 컨테이너의 상태를 나타냅니다. 가능한 값은 다음과 같습니다.
- 0: success - 컨테이너가 건강하고 사용할 준비가되었습니다
- 1: unhealthy - 컨테이너가 제대로 작동하지 않습니다
- 2: reserved - 이 종료 코드를 사용하지 마십시오
예를 들어 웹 서버가 3 초 내에 사이트의 메인 페이지를 제공 할 수 있도록 5 분마다 확인하려면 다음을 수행하십시오.
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
실패한 프로브를 디버그하기 위해 명령이 stdout 또는 stderr 에 기록하는 모든 출력 텍스트 (UTF-8 인코딩)는 상태에 저장되며 docker inspect
를 사용하여 쿼리할 수 있습니다. 이러한 출력은 짧게 유지해야합니다 (처음 4096 바이트 만 현재 저장 됨).
컨테이너의 상태가 변경되면 health_status
이벤트가 새로운 상태로 생성됩니다.
HEALTHCHECK
기능이 Docker 1.12 에 추가되었습니다.
SHELL
SHELL ["executable", "parameters"]
SHELL
명령은 shell 형태의 명령에 사용된 기본 쉘을 재정의 할 수있게 합니다. Linux 에서 기본 쉘은 ["/bin/sh", "-c"]
이고 Windows 에서는 ["cmd", "/S", "/C"]
입니다. SHELL
명령은 Dockerfile 에서 JSON 형식으로 작성되어야합니다.
SHELL
명령은 일반적으로 사용되는 매우 다른 두 가지 고유 쉘인 cmd
와 powershell
이 있으며 sh
를 포함하여 사용 가능한 대체 쉘이있는 Windows 에서 특히 유용합니다.
SHELL
명령은 여러 번 나타날 수 있습니다. 각 SHELL
명령어는 이전의 모든 SHELL
명령어를 무시하고 이후의 모든 명령어에 영향을 줍니다. 예를 들면 다음과 같습니다.
FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
Dockerfile 에서 shell 형식의 명령이 RUN
, CMD
및 ENTRYPOINT
인 경우 SHELL
명령의 영향을 받을 수 있습니다.
다음 예제는 SHELL
명령을 사용하여 간소화할 수있는 Windows 에서 발견되는 일반적인 패턴입니다.
...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
docker 가 호출한 명령은 다음과 같습니다.
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
이것은 두 가지 이유로 비효율적입니다. 먼저 불필요한 cmd.exe 명령 프로세서 (일명 셸)가 호출됩니다. 둘째, shell 형식의 각 RUN
명령에는 명령 앞에 추가 powershell -command
가 필요합니다.
이를보다 효율적으로 만들기 위해 두 가지 메커니즘 중 하나를 사용할 수 있습니다. 하나는 다음과 같은 JSON 형식의 RUN 명령을 사용하는 것입니다.
...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
JSON 형식은 명확하고 불필요한 cmd.exe 를 사용하지 않지만 큰 따옴표와 이스케이프를 통해 더 자세한 정보가 필요합니다. 대체 메커니즘은 SHELL
명령과 shell 양식을 사용하여 Windows 사용자를 위해 더욱 자연스럽게 구문을 작성하는 것입니다. 특히 escape
구문 분석기 지시문과 결합 된 경우:
# escape=`
FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
결과는:
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
---> Running in 6fcdb6855ae2
---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
---> Running in d0eef8386e97
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/28/2016 11:26 AM Example
---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
---> Running in be6d8e63fe75
hello world
---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\docker\build\shell>
SHELL
명령어는 쉘 작동 방식을 수정하는 데에도 사용할 수 있습니다. 예를 들어, Windows 에서 `SHELL cmd /S /C /V:ON|OFF 를 사용하면 지연된 환경 변수 확장 의미가 수정 될 수 있습니다.
zsh
, csh
, tcsh
등과 같은 대체 쉘이 필요한 경우 SHELL
명령을 Linux 에서도 사용할 수 있습니다.
SHELL
기능은 Docker 1.12 에 추가되었습니다.
External implementation features
이 기능은 BuildKit 백엔드를 사용하는 경우에 만 사용할 수 있습니다.
Docker 빌드는 구문 지시문과 함께 빌더의 외부 구현을 사용하여 사용 가능한 캐시 마운트, 빌드 비밀 및 SSH 전달과 같은 실험 기능을 지원합니다. 이러한 기능에 대해 알아 보려면 BuildKit 리포지토리의 설명서를 참조하십시오.
Dockerfile examples
아래는 Dockerfile 구문의 몇 가지 예를 보여줍니다.
# Nginx
#
# VERSION 0.0.1
FROM ubuntu
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# Firefox over VNC
#
# VERSION 0.3
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
# Multiple images example
#
# VERSION 0.1
FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f
FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.
0