Dockerfile

Tool/Docker 2016. 2. 4. 00:13
# 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 -'echo "firefox" >> /.bashrc'
 
EXPOSE 5900
CMD    ["x11vnc""-forever""-usepw""-create"]
cs



위처럼 특정 디렉토리에 Dockerfile 을 만들면 docker build 명령으로 이 파일과 컨텍스트를 기반으로 이미지를 생성할 수 있다.

컨텍스트는 로컬 PATH 나 Git URL 에 지정된 위치에 있는 파일들을 말한다.


Dockerfile 에는 새 이미지를 만들기 위한 각종 명령/설정을 순서대로 작성한다.

베이스 이미지, 추가적으로 패키지를 설치하기 위한 명령, 기타 실행하고 설정할 명령들을 명시한다.

빈 디렉토리에 컨텍스트를 만들어 각 Dockerfile 과 빌드에 필요한 파일들을 넣어 빌드할 수 있도록 한다.

이미지 생성에 불필요한 파일 등은 .dockerignore 파일을 사용하여 빌드에서 제외시켜 빌드 성능을 높일 수 있다.



공통


- Docker 는 Dockerfile 에 작성된 명령들을 순서대로 처리한다.

- 각 명령은 이미지의 새 레이어를 만들며, 127개 이상의 레이어를 가질 수 없다.

- 주석은 # 를 사용한다.

- <명령> <매개변수> 형식으로 사용되며, 인수를 구분하기 위해 명령은 대문자를 사용한다.

- Dockerfile 의 첫번째 명령은 반드시 베이스 이미지를 지정하는 FROM 명령으로 시작한다.

- exec form 의 경우 JSON 배열로 파싱되므로 큰따옴표(")를 사용한다.


다음은 Dockerfile 에 명시할 수 있는 명령들이다.



FROM


FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
cs


어떤 이미지를 기반으로 새 이미지를 생성할 것인지 지정한다.

로컬 호스트에 베이스 이미지가 존재하지 않으면 Docker Hub 에서 받아온다.

가능하면 official 저장소의 이미지, 또 완전한 기능을 하며 크기가 작은 Alpine 이미지를 사용하도록 한다.



MAINTAINER


MAINTAINER <name>
cs


이미지를 생성한 사람의 정보를 설정한다.



RUN


RUN /bin/sh script (shell form)
RUN ["executable""param1""param2"] (exec form)
RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
cs


FROM 에서 설정한 이미지에서 스크립트나 명령을 실행한다.

exec 형식의 경우, 명령을 실행하는 쉘을 지정하여 사용할 때 주로 사용한다.

너무 긴 구문은 가독성과 유지보수를 생각해서 백슬래시(\)로 여러 행을 만들어 구분한다.


# use /bin/sh format
RUN apt-get install -y nginx
# no shell format
RUN ["apt-get""install""-y""nginx"]
cs


RUN apt-get update && apt-get install -y \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    lxc=1.0* \
    mercurial \
    ruby1.9.1 \
    s3cmd=1.1.* \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*
cs


package-foo=1.3.* 처럼 특정 패키지 버전을 명시하여 캐시를 무효화 할 수도 있다.

/var/lib/apt/lists/ 디렉토리의 모든 파일을 삭제하면, 이미지 크기를 줄이는데 도움이 된다.



CMD


CMD ["executable","param1","param2"] (exec form)
CMD ["param1","param2"] (ENTRYPOINT의 파라미터)
CMD command param1 param2 (shell form)
cs


컨테이너가 시작되었을 때 이미지에 포함된 소프트웨어를 인수와 함께 실행하는데 사용한다.

Dockerfile 에서 CMD 명령은 한 번만 사용 가능하며, 여러 개의 CMD 를 작성할 경우 맨 마지막 명령만 동작한다.

exec form 내에 변수를 사용하려면 shell form 을 사용하던지 shell 처리 exec form 을 사용해야 한다.


CMD [ "echo""$HOME" ] (X)
CMD [ "sh""-c""echo""$HOME" ] (O)
cs



ENTRYPOINT


ENTRYPOINT ["executable""param1""param2"] (exec form)
ENTRYPOINT command param1 param2 (shell form)
cs


컨테이너가 시작되었을 때 실행할 스크립트나 명령을 명시하며 CMD 명령보다 선행된다.

docker run -i -t --rm -p 80:80 nginx 라고 커맨드 라인에 입력한 매개변수 nginx 는 ENTRYPOINT 의 뒤에 추가되고, CMD 에 사용된 모든 요소를 덮어 씌운다.

--entrypoint 플래그를 사용하면 ENTRYPOINT 를 덮어 씌울 수 있다.



LABEL


LABEL <key>=<value> <key>=<value> <key>=<value> ...
cs


이미지에 메타데이터를 추가한다.


LABEL "com.example.vendor"="ACME Incorporated" \
      com.example.label-with-value="foo" \
      version="1.0" \
      description="This text illustrates \
      that label-values can span multiple lines." \
      multi.label1="value1" \
      multi.label2="value2" \
      other="value3"
cs


docker inspect 명령시 이미지 Label 을 확인할 수 있다.


"Labels": {
    "com.example.vendor""ACME Incorporated"
    "com.example.label-with-value""foo",
    "version""1.0",
    "description""This text illustrates that label-values can span multiple lines.",
    "multi.label1""value1",
    "multi.label2""value2",
    "other""value3"
},
cs



EXPOSE


EXPOSE <port> [<port>...]
cs


EXPOSE 명령으로 컨테이너가 연결(Listen)할 포트를 지정한다. --expose 옵션과 동일하다.

EXPOSE 명령으로 호스트에서 접근 가능한 컨테이너의 포트를 만들지는 않으며 포트를 외부에 노출하려면 -p, -P 옵션을 사용한다.

하나의 포트를 EXPOSE 하고 또 다른 포트로 외부에 노출할 수 있다.



ENV


ENV <key> <value>
ENV <key>=<value> ...
cs


컨테이너가 설치하는 소프트웨어에 대해 ENV 를 사용하여 PATH 환경 변수를 업데이트 할 수 있다. -e --env 옵션과 동일하다.

정의된 환경 변수는 Dockerfile 의 거의 모든 명령에 $ 표시로 적용 가능하다.


FROM busybox
ENV foo /bar
WORKDIR ${foo}   # WORKDIR /bar
ADD . $foo       # ADD . /bar
COPY \$foo /quux # COPY $foo /quux
 
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && ...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
cs



ADD


ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
cs


<src> 경로의 파일/디렉토리를 컨테이너의 경로<dest>에 복사한다.

<src> 는 컨텍스트 디렉토리를 기준으로 하며 컨텍스트 외부로의 상대/절대 경로는 사용할 수 없다.

로컬에 있는 압축 파일(tar.gz, tar.bz2, tar.xz)은 압축을 해제하고 tar를 풀어서 추가된다. 단, 인터넷에 있는 파일 URL은 압축만 해제한 뒤 tar 파일이 그대로 추가된다.

url 방식의 압축파일일 경우 압축만 해제하고 tar 는 해제하지 않아 이미지 용량이 늘어나므로 RUN wget 이나 curl 을 이용한다.

<src> 의 내용이 변경된 경우, ADD 이후의 모든 명령에는 캐시가 무효화된다.

ADD ./ /hello/ 와 같이 현재 디렉터리를 추가할 때 .dockerignore 파일에 설정한 파일과 디렉터리는 제외된다.


ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir          # adds "test" to /absoluteDir
cs



COPY


COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
cs


<src> 경로의 파일/디렉토리를 컨테이너의 경로<dest>에 복사한다.

ADD 명령과 복사한다는 기능은 같지만, 로컬 파일을 컨테이너에 복사하는 기능만을 하며, 명확하기 때문에 ADD 명령보다 선호한다.

ADD와는 달리 COPY는 압축 파일을 복사할 때 압축을 해제하지 않고 압축 파일 그대로 복사하며 파일 URL도 사용할 수 없다.

COPY ./ /hello/ 와 같이 현재 디렉터리를 추가할 때 .dockerignore 파일에 설정한 파일과 디렉터리는 제외된다.



VOLUME


VOLUME ["/data"]
cs


호스트나 다른 컨테이너의 볼륨으로 지정될 마운트 포인트를 생성한다.

실제 연결은 -v <host_dir>:<container_dir> 옵션을 사용하여 컨테이너에 저장될 디렉토리를 호스트에 저장하도록 설정한다.



USER


USER daemon
cs


명령을 실행할 사용자 계정이나 UID 를 설정한다. USER 뒤에 오는 RUN, CMD, ENTRYPOINT에 적용된다.



WORKDIR


WORKDIR /path/to/workdir
cs


WORKDIR 뒤에 오는 RUN, CMD, ENTRYPOINT, ADD, COPY 의 명령이 실행될 디렉토리를 설정한다.

명확하게 항상 절대 경로를 사용하는 것이 좋다.

ARG 와 ENV 명령으로 동일한 이름을 정의한다면, ENV 값이 우선이다.



ARG


ARG <name>[=<default value>]
cs


docker build --build-arg <varname>=<value> 플래그를 사용하여 빌드시 사용자가 전달할 수 있는 변수를 정의한다.


FROM busybox
ARG user1
ARG buildno=1
...
cs


미리 정의된 ARG 변수들 (따로 정의할 필요없음)


- HTTP_PROXY

- http_proxy

- HTTPS_PROXY

- https_proxy

- FTP_PROXY

- ftp_proxy

- NO_PROXY

- no_proxy



ONBUILD


ONBUILD 명령은 Dockerfile 로 생성된 이미지를 베이스 이미지로 하는 자식 이미지로부터 생성되는 컨테이너에서 실행된다.

FROM, MAINTAINER, ONBUILD를 제외한 모든 Dockerfile 명령을 사용할 수 있다.

자식의 자식 이미지로는 상속되지 않는다.


[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
cs



STOPSIGNAL


STOPSIGNAL signal
cs


종료될 컨테이너에 보내질 호출 신호를 설정한다.

신호는 커널의 시스템 콜 테이블의 숫자 9 나 SIGNAME 인 SIGKILL 가 될 수 있다.



Docker cache


Docker 는 Dockerfile 에 지정된 순서로 이미지를 빌드할 때, 빌드 속도를 향상시키기 위해 캐시에서 기존 이미지를 재사용한다.

예로, RUN 명령에서 apt-get update 과 apt-get install 명령을 한 줄에 붙여 사용하지 않으면, apt-get update 명령이 변경되지 않았을 때 캐시에서 가져오므로, 그 뒤의 install 패키지들은 원하는 최신 버전을 사용할 수 없게 된다.

docker build 명령에서 --no-cache=true 옵션을 추가하거나 ADD 명령으로 캐시를 무효화할 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,