이번 포스팅에서는 Dockerfile에 작성가능한 지침목록과 내용들에 대해 살펴볼생각이다.
공식문서 를 바탕으로 정리한 내용이지만, 오역이나 잘못이해한 부분이 있을 수 있으므로 자세한 내용은 직접 확인해보는 것을 추천한다.
지침과 인수를 쉽게 구분하기위해 관례적으로 지침은 대문자로 작성하는 것이 권장된다.
FROM: 후속 명령어들이 동작할 배경환경 지정RUN: 현재 이미지 위에 새로운 레이어를 만드는 명령들을 실행
즉, 빌드환경 구성을 위한 배경설정에 사용CMD: 이미지를 컨테이너화 시킬 때, 동작할 명령어들을 설정
ENTRYPOINT에 대한 기본 인수 제공, 또는 컨테이너에서 동작될 임시 명령어 사용 시에 권장ENTRYPOINT: 이미지를 컨테이너화 시킬 때, 동작할 명령어들을 설정
컨테이너를 하나의 실행파일로 사용하는 경우에 권장LABEL: 이미지에 대한 메타데이터 제공EXPOSE: 컨테이너가 런타임 시에 열어놓은 포트를 지정ENV: 빌드 및 이미지에서 유지되는 환경변수 값 설정ADD:<src>의 파일이나 디렉토리를 복사하여 이미지의 파일시스템인<dest>에 추가
Git이나 URL 등에서 파일이나 디렉토리를 가져오는 목적COPY:<src>의 파일이나 디렉토리를 복사하여 이미지의 파일시스템인<dest>에 추가
이미지나 특정 빌드 스테이지에서 파일이나 디렉토리를 가져오는 목적VOLUME: 마운트 지점을 생성하고, 호스트나 다른 컨테이너에서 관리하는 목적으로 사용USER: 현재 빌드 스테이지의 이어지는 부분의 기본 사용자 및 그룹으로 사용할 사용자 이름이나 UID, 그리고 사용자 그룹이나 GID를 설정WORKDIR:RUN,CMD,ENTRYPOINT,COPY,ADD명령이 실행될 디렉토리를 설정ARG: 사용자가docker build명령에 전달하여 빌드시점에만 유효한 변수정의ONBUILD: 이미지가 다른 빌드의 base로 사용될 때, 실행될 트리거 명령을 이미지에 추가STOPSIGNAL: 컨테이너 종료 시에 전송되는 시스템 호출 신호를 설정HEALTHCHECK: Docker가 컨테이너의 작동을 확인하기 위한 테스트방법 제공SHELL: 명령의 쉘 형식에 사용되는 기본 쉘을 재정의
Dockerfile 내의 후속 줄들이 처리되는 방식을 지정하는데 사용된다.
# directive=value의 형태의 특수 주석형태로 작성되며, 동일한 지시문을 여러번 작성하면 무시된다.
사용가능한 지시문(directive) 목록은 아래와 같다.
syntax : Dockerfile의 구문 버전 설정# syntax=docker/dockerfile:1로 작성하면 최신 stable 버전 사용을 의미한다.escape : 이스케이프 문자 지정check : 빌드 검사와 관련하여 특정 검사를 비활성화하거나, 검사 실패시 경고여부를 설정기본적으로 directive는 대소문자를 구분하지 않지만, 소문자로 작성되는게 규칙이다.
아래는 유효하지 않은 파서 지시문들을 보여준다.
# direc \
tive=value
줄바꿈
# directive=value1
# directive=value2
FROM ImageName
동일 directive로 두번 작성됨
FROM ImageName
# directive=value
지침이후에 작성되었으므로, 주석으로 처리
# About my dockerfile
# directive=value
FROM ImageName
주석 뒤에 나타나므로, 주석으로 처리
ENV 지침을 이용하면 빌드명령에서 입력받거나 직접 환경변수 값을 설정하는게 가능하다.
이는 컨테이너화된 인스턴스에서도 유지되는 값이며,
빌드를 위한 실행환경 구성이나 컨테이너의 기본 환경변수 값을 세팅하는데 사용된다.
Dockerfile에서 환경변수는 $variable_name이나 ${variable_name}의 형태로 표시된다.
각 표기방법은 동등하며, 중괄호 표기법은 보통 공백이 없는 변수이름에 사용된다.
중괄호 표기법은 표준 bash수정자를 지원한다.
예를들어 ${variable:-word}의 경우, variable이 주어지지 않았을 때 word가 사용된다는 의미이고
${variable:+word}의 경우, variable이 주어지면 word가 사용되고, 아닌경우 공백이 사용된다는 의미다.
특정 구문버전(
# syntax=docker/dockerfile-upstream:master)에서 변수가 대체되는 예시는 링크를 참고하자
후속 명령어들이 동작할 배경환경 지정
모든 Dockerfile들의 시작부분에 오는 지침으로, 빌드동작이 수행될 환경을 설정한다.
Dockerfile은 반드시 초반에 해당 지침이 와야한다.
빌드인수인 ARG나 주석, 혹은 주석형태의 parser directive가 예외적으로 FROM보다 앞서 작성될 수 있다.
FROM [--platform=<platform>] <image> [AS <name>]
# or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
# or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM은 후속 명령어들이 동작할 배경환경을 지정하는데 사용된다.
즉, FROM 이후에 작성되는 후속 명령어들은 FROM에서 지정한 이미지에서 동작한다고 봐도 무방하다.
앞서 설명했듯이 ARG 지침만이 FROM앞에 작성될 수 있으며, 이를통해 배경 이미지를 설정할 때 빌드명령어를 통해 ARG로 인수값을 전달하여 특정 태그 혹은 버전의 배경 이미지로 Dockerfile이 동작하게 구성할 수 있다.
예를들어,
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
이런식으로 구성하면 docker build --build-arg CODE_VERSION={버전} . 형식으로 빌드가 동작할 배경이미지의 버전을 지정하는 식으로 사용할 수 있다. 유의할 사항으로 FROM앞에 지정한 ARG는 후술 명령어에서 사용하는게 불가능하다. 만약, 사용하고싶다면 FROM이후에 ARG {인수명}을 한번 더 작성해줘야한다.
즉,
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
이런식으로 FROM이후에 ARG를 한번 더 작성해야한다.
빌드이미지에
tag나digest를 생략하면 기본적으로 lastest가 사용된다.또한,
FROM지침에AS name의 형태로 식별자를 부여하는 것도 가능하다.
이렇게 식별자를 부여하면, 생성된 이미지를 이후의 빌드 스테이지에서 해당 식별자로 참조하는데 사용할 수 있다이외에
FROM이 멀티플랫폼을 지원한다면, 선택적으로 빌드명령에서--platform옵션을 사용해 이미지의 플랫폼을 지정할 수도 있다.
FROM은 한 Dockerfile에 여러번 작성될 수 있다.
한번에 여러개의 이미지를 생성하거나, 한 빌드 스테이지가 다른 빌드 스테이지의 종속성이 되도록 구성할 때 사용된다.
이때, 한 빌드 스테이지가 끝나면 생성된 이미지의 ID를 기록하고 새로운 빌드 스테이지가 시작될 때 이전에 생성된 상태들은 초기화된다.
현재 이미지 위에 새로운 레이어를 만드는 명령들을 실행
즉, 빌드환경 구성을 위한 배경설정에 사용
# Shell form:
RUN [OPTIONS] <command> ...
# Exec form:
RUN [OPTIONS] [ "<command>", ... ]
RUN지침은 shell형태와 exec형태가 존재한다.
RUN apt-get dist-upgrade -y 와 같은 명령들은 기본적으로 캐시되어 다음 빌드에서도 사용된다.
이는 docker build --no-cache나 ADD, COPY에 의해 캐시되지 않게 할 수 있다.
일반적으로 linux명령을 작성하듯이 shell을 이용해 명령들을 작성한다.
RUN <<EOF
apt-get update
apt-get install -y curl
EOF
위 형태처럼, 이스케이프 문자(EOF, \)를 활용해 여러개의 명령어를 한 RUN 지침안에 작성하는게 가능하다.
기본적으로 항상 명령 shell을 사용하여 명령어를 수행하지만, SHELL 지침을 이용한다면 변경하는 것도 가능하다
SHELL ["/bin/bash", "-c"] RUN echo hello
쉘 문자열 munging을 방지하고, 특정 명령 shell이나 다른 실행파일을 사용해 명령을 실행할 수 있게 해준다.
JSON 배열구문을 사용하며, 배열에는 명령어, flag, 인수 등의 값이 작성된다.
RUN [ "sh", "-c", "echo $HOME" ]
위 예시에 작성된 RUN 지침을 해석해보면 아래의 형태가 된다.
- 명령 실행을 위해
sh쉘을 사용-c옵션을 통해 후술될 문자열이 실행 코드임을 의미- 실행될 명령으로
echo $HOME명령 작성
Exec형태는 JSON 형태를 사용하기 때문에 백슬래시(\)를 이스케이프 시퀀스로 사용한다.
따라서, \를 사용해야하는 상황이라면 \\와 같은 형식으로 사용해야한다.
munging( 멍잉?, 먼징? )
docker 문서를 살펴보면서 처음 보는 단어라 당황했다.
위키에 따르면, 데이터 랭글링(data wrangling) 혹은 데이터 먼징(data munging)이라고도 불리며,
원본데이터를 손쉽게 사용할 수 있도록 가공하는 과정을 의미한다.shell형태로 명령을 작성한다고 가정해보자.
CMD echo "Hello World"위
CMD지침은 실제 동작에서/bin/sh -c "eche Hello World"와 같이 변환되어 동작한다.
즉, 쉘에서 실행되기 적합한 형태로 가공되는 과정( munging )이 들어간다.
RUN은 mount, network, security 총 3가지의 옵션을 지원한다.
상세내용은 공식문서를 참고하는 것을 추천한다.
RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]
RUN 지침에서 접근할 수 있는 파일시스템 마운트를 생성
보통 호스트 파일시스템이나 다른 빌드 스테이지에서 생성된 파일을 마운트하여 빌드 컨테이너에서 접근하는 용도로 사용된다.
작성 형태에서 확인할 수 있듯이 type을 이용해 마운트 유형을 지정할 수 있다. 간략하게 나타내면 아래와 같다.
bind: 호스트 파일시스템을 빌드 컨테이너에서 읽기 전용으로 마운트cache: 빌드 컨테이너가 컴파일러와 패키지 관리자를 위한 디렉토리를 캐시
apt-get update처럼 반복적으로 이뤄지는 동작의 수행시간 단축을 위함tmpfs: 임시 파일시스템을 컨테이너와 마운트secret: 이미지에 반영하지 않고, 토큰이나 private key값 등을 컨테이너에서 접근할 수 있도록 마운트ssh: 빌드컨테이너가 SSH agents를 통해 SSH key에 접근할 수 있도록 마운트
RUN --network=<TYPE>
명령이 실행될 네트워크 환경제어를 위한 옵션으로, 지원하는 네트워크 타입은 아래와 같다.
default: 기본 네트워크 사용하여 동작none: 네트워크 접근 없이 동작host: 호스트의 네트워크 환경을 사용하여 동작
RUN --security=<sandbox|insecure>
명령에 대한 보안정책 관리
insecure 모드를 활성화하면 더 높은 권한을 사용할 수 있다.
공통적으로 이미지를 컨테이너화 시킬 때, 동작할 명령어들을 설정
Dockerfile내에서 가장 마지막에 작성된 지침만 유효
ENTRYPOINT에 대한 기본 인수 제공, 또는 컨테이너에서 동작될 임시 명령어 사용 시에 권장
# exec form
CMD ["executable","param1","param2"]
# exec form, ENTRYPOINT 지침의 기본 파라미터
CMD ["param1","param2"]
# shell form
CMD command param1 param2
빌드시점에는 영향을 미치지 않으며, 이미지를 컨테이너화 할 때만 관여한다.
주 목적은 컨테이너를 실행할 때, 기본값을 제공하는 것이다.
이 기본값에는 실행파일이나 명령어가 포함된다. 만약, 이러한 기본값을 제공하지 않는경우에는 반드시 ENTRYPOINT와 함께 사용해야한다.
CMD를ENTRYPOINT에 대한 기본 옵션제공 용도로 사용한다면, 두 지침 모두 exec형태로 작성하는 것이 권장된다.
컨테이너를 하나의 실행파일로 사용하는 경우에 권장
# exec form
ENTRYPOINT ["executable", "param1", "param2"]
# shell form
ENTRYPOINT command param1 param2
docker run명령에 포함된 인수들은 exec형식의 ENTRYPOINT에 설정된 요소들 뒤에 추가된다.
이렇게 추가되는 옵션들은 CMD를 통해 지정된 옵션들을 대신하여 적용된다.
예를들어, 아래 Dockerfile이 있다고 가정해보자
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
ENTRYPOINT로 인해, 컨테이너 생성 시에 top -b 명령이 실행될 것이다.
이때, CMD가 존재하므로 실제로 실행되는 명령은 top -b -c가 된다.

이미지 빌드 및 실행을 해보면 원하는 대로 동작하는 것을 볼 수 있다.
이때, 컨테이너를 실행하면서 추가옵션을 제공해보자


추가옵션을 제공할 경우, CMD에 작성된 추가옵션을 덮어쓴다.
따라서, -c 옵션이 -H로 변경된 것을 확인할 수 있다.
이미지에 대한 메타데이터 제공
LABEL <key>=<value> [<key>=<value>...]
키-값 쌍의 형태로 이미지에 메타데이터를 추가하는 용도로 사용된다.
이렇게 추가된 메타데이터들은 docker image inspect 명령으로 확인할 수 있다.
FROM ubuntu
LABEL my-key="hello"
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
이런 Dockerfile로 생성된 이미지를 대상으로 docker image inspect 명령을 수행해보자

Config - Labels에 직접 추가한 LABEL인 my-key가 추가된 것을 확인할 수 있다.
만약, FROM의 base 이미지에 정의된 LABEL과 동일한 이름의 메타데이터를 추가하면 재정의된다.
컨테이너가 런타임 시에 열어놓은 포트를 지정
EXPOSE <port> [<port>/<protocol>...]
TCP/UDP 프로토콜을 지정하는게 가능하며, 프로토콜을 지정하지 않으면 기본값으로 TCP가 사용된다.
실제로 포트를 개방하는 역할을 수행하지는 않으며,
이미지를 빌드하는 사람과 컨테이너를 실행하는 사람 사이에서 어떤 포트를 열어야하는지를 명시하는 문서역할을 한다.
실제 포트를 개방하는 작업은 docker run 명령의 -p 옵션을 통해 이뤄진다.
만약, -P 옵션을 사용하면 EXPOSE에 명시된 포트들이 모두 개방된다.
이 경우, 매핑되는 호스트 포트는 자동으로 할당된다 (EXPOSE와 다른 포트가 매핑될 수 있다 )
docker network명령을 이용하면 컨테이너간 통신을 위한 별도의 네트워크를 생성할 수 있다.이렇게 생성된 네트워크에 포함된 컨테이너들은 포트 개방과 무관하게 모든 포트를 사용하여 통신할 수 있다.
자세한 내용은 공식 문서를 참고하자
빌드 및 이미지에서 유지되는 환경변수 값 설정
ENV <key>=<value> [<key>=<value>...]
키-값 쌍의 형태로 환경변수를 설정할 수 있다.
이렇게 설정된 환경변수는 해당 스테이지를 상속하는 다른 빌드 스테이지에서도 유지되며, 최종적으로 생성되는 이미지에서도 유지된다. 따라서, 특정 명령에서만 사용 혹은 유지되어야하는 경우에는 RUN에 직접 환경변수를 전달하거나 ARG를 사용해야한다.
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy
한 지침내에 여러개의 환경변수를 설정하는 것과 여러 지침으로 나눠 설정하는 것은 동일한 의미를 가진다.
ADD와 COPY는 모두 외부의 파일이나 디렉토리를 이미지의 파일시스템으로 복사하여 가져온다는 점에서 유사하다.
차이점은 어떤 대상으로부터 복사해오는가에 있다.
ADD는 외부 URL이나 Git Repository에서 파일을 가져올 수 있으며,
빌드 컨텍스트에서 파일을 가져올 때 자동으로tar파일을 추출한다.
COPY는 멀티스테이지의 특정 빌드 스테이지에서 파일이나 디렉토리를 가져올 수 있다.파일이나 디렉토리가 최종 생성될 이미지에서 필요하지 않은 경우에는
RUN지침에서target을 통해 파일을 가져오는게 더 효과적이다.
<src>의 파일이나 디렉토리를 복사하여 이미지의 파일시스템인<dest>에 추가
ADD [OPTIONS] <src> ... <dest>
COPY [OPTIONS] <src> ... <dest>
# 경로에 공백이 포함되는 경우 사용
ADD [OPTIONS] ["<src>", ... "<dest>"]
COPY [OPTIONS] ["<src>", ... "<dest>"]
ADD의 <src>에는 빌드 컨텍스트, 원격 URL, Git Repository 등이 올 수 있다.
COPY의 <src>에는 빌드 컨텍스트, 빌드 스테이지, 명명된 컨텍스트, 이미지 등이 올 수 있다.
예를들어, 빌드 컨텍스트의 file1.txt와 file2.txt를 이미지 내의 /usr/src/things/에 추가하는 명령은 아래와 같다.
ADD file1.txt file2.txt /usr/src/things/
COPY file1.txt file2.txt /usr/src/things/
원격 URL이나 Git Repository에서 파일 혹은 디렉토리를 복사하는 경우에는 아래와 같은 형식으로 작성할 수 있다.
ADD https://example.com/archive.zip /usr/src/things/
ADD git@github.com:user/repo.git /usr/src/things/
특정 빌드 스테이지에서 파일을 복사하는 경우에는 아래와 같은 형식으로 작성할 수 있다.
FROM golang AS build
WORKDIR /app
RUN --mount=type=bind,target=. go build -o /myapp ./cmd
COPY --from=build /myapp /usr/bin/
빌드 컨텍스트, tar 파일, 원격 URL, Git Repository 각각에서 파일을 가져오는 동작은 공식문서를 참고하자
<dest>가 /로 시작된다면 절대 경로로 해석된다.
소스파일은 현재 빌드 스테이지의 루트를 기준으로 지정된 대상에 복사한다.
# /abs/test.txt 에 생성
ADD test.txt /abs/
<dest>가 /로 시작되지 않는다면 상대 경로로 해석된다.
WORKDIR를 통해 설정된 작업경로를 기준으로 판단되며, 아래 예시를 참고하자
WORKDIR /usr/src/app
# /usr/src/app/rel/test.txt 에 생성
ADD test.txt rel/
만약,
<dest>경로에 포함된 디렉토리가 없다면 생성된다.
공통적으로 사용되는 옵션
--chown --chmod: 리눅스 컨테이너를 빌드하는데 사용되는 Dockerfile에서만 지원
--chown:<user>:<group>형태로 복사된 파일이나 디렉토리의 소유자 변경에 사용( UID, GID혹은 이름 지정 )--chmod:<perms>형태로 파일 권한변경에 사용 ( UGO 기준 rwx를 각각 4,2,1로 최대 권한기준 777 )--link: 복사된 파일이 자체 레이어에도 독립적으로 유지되며, 이전 레이어에서 명령이 변경되어도 무효화되지 않음
각 지침에 의해 파일이 추가되더라도, 독립적인 레이어에 추가되므로 이전 레이어에 영향을 받지 않음.
병합을 통해 최종적인 파일시스템이 구축되므로 반복적인 작업이 없어져서 빌드속도가 빨라짐. 참고--exclude: 제외할 파일 경로 표현식 지정
ADD에서 사용되는 옵션
--keep-git-dir: 기본적으로 Git Repository에서.git을 제외하고 파일 및 디렉토리를 가져오는 설정을 비활성화--checksum: HTTP(S)<src>에 대해<algorithm>:<hash>의 형태로 외부 자원에 대한 checksum을 검증하여 파일의 무결성 검사
COPY에서 사용되는 옵션
--from: 파일을 가져올 대상(이미지, 스테이지, 컨텍스트) 지정--parents:<src>에 대한 부모 디렉토리 보존, 기본 옵션은false# syntax=docker/dockerfile:1-labs FROM scratch COPY ./x/a.txt ./y/a.txt /no_parents/ COPY --parents ./x/a.txt ./y/a.txt /parents/ # /no_parents/a.txt, 부모 디렉토리가 보존되지 않으므로 a.txt를 덮어씀 # /parents/x/a.txt # /parents/y/a.txt
마운트 지점을 생성하고, 호스트나 다른 컨테이너에서 관리하는 목적으로 사용
VOLUME ["/data"]
볼륨을 이용하면 호스트나 외부 컨테이너의 파일시스템과 현재 생성되는 컨테이너의 경로를 연결시켜 외부에서 파일을 관리할 수 있게 된다. 해당 지침은 컨테이너 생성과 함께 볼륨을 생성하게 해준다.
볼륨과 관련된 자세한 내용은 공식 문서를 참고하자.
추후에 관련된 포스팅도 작성할 예정이다
예를들어, 아래 Dockerfile로 컨테이너를 생성한다고 가정해보자
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol


컨테이너를 생성하고, docker volume inspect myvol를 통해 볼륨이 생성된 것을 확인할 수 있다.
이렇게 생성된 볼륨은 호스트의 Mountpoint와 서로 연결된다.
현재 윈도우에서 WSL2를 이용해 Docker를 테스트하고 있으므로 직접적으로 해당 경로를 방문하기는 힘들다.
\AppData\Local\Docker\wsl\data 경로를 확인해보면 ext4.vhdx라는 파일이 존재하는데, 해당 파일에 Docker와 관련된 파일이 존재한다.
따라서, 해당 경로를 마운트하는 컨테이너를 생성하면 내부에 접근이 가능하다

해당 경로로 접근해서 살펴보면 Dockerfile에서 추가한 greeting이 존재하는 것을 확인할 수 있다.
현재 빌드 스테이지의 이어지는 부분의
기본 사용자 및 그룹으로 사용할 사용자 이름이나 UID, 그리고 사용자 그룹이나 GID를 설정
USER <user>[:<group>]
# or
USER <UID>[:<GID>]
이어지는 RUN, ENTRYPOINT, CMD지침을 동작할 사용자를 지정하는데 사용된다.
지정되는 사용자에게 기본 그룹이 없다면 루트그룹으로 실행된다.
해당 지침을 생략하고 실행시킨 컨테이너에서 사용자는 기본적으로 root가 된다.
RUN,CMD,ENTRYPOINT,COPY,ADD명령이 실행될 디렉토리를 설정
WORKDIR /path/to/workdir
해당 지침이 없다면 FROM에서 설정된 WORKDIR로 지정된다.
동일한 Dockerfile에서 WORKDIR가 여러번 작성될 수 있는데, 이 경우에 상대경로로 동작한다
예를들어, 아래 경우를 살펴보자
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
이 경우, 최종 pwd의 결과는 /a/b/c가 된다.
사용자가
docker build명령에 전달할 수 있는 변수를 정의
ARG <name>[=<default value>] [<name>[=<default value>]...]
docker build에서 --build-arg <varname>=<value> 형태로 값을 전달할 수 있다.
아래 예시처럼 빌드명령에서 값이 주어지지 않았을 경우, 기본값을 설정할 수도 있다.
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
ARG 변수의 범위는 해당 빌드 스테이지에서 선언된 줄 이후부터 유효하며, 최종 이미지 생성에서는 유지되지 않는다.
ARG변수 생성 전에는 이미 사용되는 변수명인지 확인해야한다.
HTTP_PROXY,HTTPS_PROXY등의 사전정의된ARG값들도 존재하며,
특정 플랫폼에서 글로벌 범위로 설정되는ARG,
BuildKit이 등록하는ARG등이 존재한다.상세 내용은 공식문서를 참고하자
ARG는 ENV와 다르게 최종 생성되는 이미지까지 유지되지는 않는다.
하지만 빌드 캐시에는 영향을 미치는데, 이전 빌드와 값이 다른 ARG 변수를 정의하는 경우에 정의 시점이 아닌 첫 사용시에 캐시미스가 발생한다. 보통 ARG이후에 오는 RUN에서 암묵적으로 ARG 변수를 사용하므로, 캐시미스가 발생할 수 있다.
예를들어, 아래의 Dockerfile을 생각해보자
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=$CONT_IMG_VER
RUN echo $CONT_IMG_VER
3번째 줄에서 실제로 ARG 변수를 사용하기 때문에, 빌드명령에서 주어지는 값이 변경될 때마다 캐시미스가 발생할 수 있다.
이미지가 다른 빌드의 base로 사용될 때, 실행될 트리거 명령을 이미지에 추가
ONBUILD <INSTRUCTION>
ONBUILD를 통해 삽입된 트리거명령은 해당 이미지를 base로 사용하는 Dockerfile의 FROM 바로 밑에 작성된 것처럼 동작한다. 삽입되는 트리거 명령은 최종 생성되는 이미지에는 유지되지 않는다.
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
이런 ONBUILD가 존재한다면, 해당 이미지를 base로 삼는 이미지의 FROM 밑에 ADD와 RUN이 삽입되는 형식이다.
ONBUILD ONBUILD같은 체인 형식의 사용은 지원하지 않는다.
컨테이너 종료 시에 전송되는 시스템 호출 신호를 설정
STOPSIGNAL signal
기본값으로 SIGTERM이 사용되며, SIG<NAME> 형태의 이름 혹은 부호없는 숫자가 사용된다.
docker run과 docker create에서 --stop-signal옵션으로 컨테이너 별 재정의가 가능하다.
Docker가 컨테이너의 작동을 확인하기 위한 테스트방법 제공
# 컨테이너 내에서 command를 실행시켜 상태 검사
HEALTHCHECK [OPTIONS] CMD command
# base 이미지를 사용하는 하위 이미지의 상태검사 비활성화
HEALTHCHECK NONE (disable any healthcheck inherited from the base image)
무한루프 등으로 인에 실행중이지만 정상적이지 않은 컨테이너를 확인하기 위한 용도로 사용된다.
한 Dockerfile에 하나만 존재할 수 있으며, 마지막 설정된 지침만 유효하다.
OPTIONS에 올 수 있는 옵션 목록은 아래와 같다
--interval={DURATION} ( 기본 30초 )--timeout={DURATION} ( 기본 30초 )--start-period={DURATION} ( 기본 0초 )--start-interval={DURATION} ( 기본 5초 )start-period 동안의 상태검사 간격--retries={N} ( 기본 3회 )결과값으로는 0(성공), 1(위험), 2(예약됨)이 존재한다.
만약, 디버깅을 원한다면 docker inspect명령으로 출력 내용을 확인할 수 있다.
또한 컨테이너의 상태가 변경될때마다 health_status 이벤트가 생성된다.
명령의 쉘 형식에 사용되는 기본 쉘을 재정의
SHELL ["executable", "parameters"]
기본적으로 설정된 쉘은 리눅스는 ["/bin/sh", "-c"], 윈도우는 ["cmd", "/S", "/C"]다.
만약 기본 쉘을 powershell로 변경하고 싶다면 아래와 같이 작성할 수 있다.
SHELL ["powershell", "-command"]
RUN Write-Host hello
기본 쉘을 변경하는 것 외에도, 쉘의 동작을 수정하는 용도로도 사용된다.
윈도우의 기본쉘은 ["cmd", "/S", "/C"]라고 설명했는데, SHELL cmd /S /C /V:ON|OFF 형식으로 동작을 수정할 수 있다.