# 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"] | 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
이미지를 생성한 사람의 정보를 설정한다.
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
호스트나 다른 컨테이너의 볼륨으로 지정될 마운트 포인트를 생성한다.
실제 연결은 -v <host_dir>:<container_dir> 옵션을 사용하여 컨테이너에 저장될 디렉토리를 호스트에 저장하도록 설정한다.
USER
명령을 실행할 사용자 계정이나 UID 를 설정한다. USER 뒤에 오는 RUN, CMD, ENTRYPOINT에 적용된다.
WORKDIR
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
종료될 컨테이너에 보내질 호출 신호를 설정한다.
신호는 커널의 시스템 콜 테이블의 숫자 9 나 SIGNAME 인 SIGKILL 가 될 수 있다.
Docker cache
Docker 는 Dockerfile 에 지정된 순서로 이미지를 빌드할 때, 빌드 속도를 향상시키기 위해 캐시에서 기존 이미지를 재사용한다.
예로, RUN 명령에서 apt-get update 과 apt-get install 명령을 한 줄에 붙여 사용하지 않으면, apt-get update 명령이 변경되지 않았을 때 캐시에서 가져오므로, 그 뒤의 install 패키지들은 원하는 최신 버전을 사용할 수 없게 된다.
docker build 명령에서 --no-cache=true 옵션을 추가하거나 ADD 명령으로 캐시를 무효화할 수 있다.