[번역]Dockerfile 레퍼런스 #3 > 서버관리자

서버관리자

서버관리자 모임 게시판 입니다.

[번역]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 명령은 컨테이너를 실행할 때 어떤 명령이 실행 될지 정의합니다. 그들의 협력을 설명하는 규칙은 거의 없습니다.

  1. Dockerfile은 CMD 또는 ENTRYPOINT 명령 중 하나 이상을 지정해야합니다.

  2. ENTRYPOINT는 컨테이너를 실행 파일로 사용할 때 정의해야합니다.

  3. ENTRYPOINT명령의 기본 인수를 정의하거나 컨테이너에서 임시 명령을 실행하는 방법으로 CMD를 사용해야합니다.

  4. 컨테이너를 대체 인수로 실행하면 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에서 그 뒤에 오는 RUNCMD 및 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에서 RUNCMDENTRYPOINTCOPY 및 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. Eg linux/amd64linux/arm/v7windows/amd64.
  • TARGETOS - OS component of TARGETPLATFORM
  • TARGETARCH - architecture component of TARGETPLATFORM
  • TARGETVARIANT - variant component of TARGETPLATFORM
  • BUILDPLATFORM - platform of the node performing the build.
  • BUILDOS - OS component of BUILDPLATFORM
  • BUILDARCH - architecture component of BUILDPLATFORM
  • BUILDVARIANT - 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를 사용하여 나중에 실행할 고급 명령을 등록하는 것입니다.

작동 방식은 다음과 같습니다.

  1. ONBUILD 명령이 발생하면 빌더는 빌드중인 이미지의 메타 데이터에 트리거를 추가합니다. 지침은 현재 빌드에 영향을 미치지 않습니다.
  2. 빌드가 끝나면 모든 트리거 목록이 이미지 OnBuild아래 이미지 매니페스트에 저장됩니다. docker inspect 명령으로 검사 할 수 있습니다.
  3. 나중에 이미지는 FROM 명령어를 사용하여 새로운 빌드의 기반으로 사용될 수 있습니다. FROM명령어 처리 과정에서 다운 스트림 빌더는 ONBUILD트리거를 찾아서 등록 된 순서대로 실행합니다. 트리거 중 하나라도 실패하면 FROM 명령이 중단되어 빌드가 실패합니다. 모든 트리거가 성공하면 FROM 명령이 완료되고 빌드는 평소대로 계속됩니다.
  4. 실행 후 최종 이미지에서 트리거가 지워집니다. 다시 말해, 그들은 "손자"빌드에 의해 상속되지 않습니다.

예를 들어 다음과 같이 추가 할 수 있습니다.

[...]
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 형식의 명령이 RUNCMD 및 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 를 사용하면 지연된 환경 변수 확장 의미가 수정 될 수 있습니다.

zshcshtcsh 등과 같은 대체 쉘이 필요한 경우 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

댓글 1개

전체 637 |RSS
서버관리자 내용 검색

회원로그인

진행중 포인트경매

  1. 참여0 회 시작24.03.28 11:15 종료24.04.04 11:15
(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT