ETC.

Dockerfile 기본 명령어

Kyle79 2020. 5. 1. 17:52

이미지를 만드는 데 사용한 Dockerfile의 기본적인 명령어를 살펴보겠습니다.

 

FROM


FROM <image>:<tag> 
FROM ubuntu:16.04


베이스 이미지를 지정합니다. 반드시 지정해야 하며 어떤 이미지도 베이스 이미지가 될 수 있습니다.

tag는 될 수 있으면 latest(기본값)보다 구체적인 버전(16.04등)을 지정하는 것이 좋습니다.

이미 만들어진 다양한 베이스 이미지는 Docker hub에서 확인할 수 있습니다.

 

LABEL


LABEL MAINTAINER <name>
LABEL MAINTAINER subicura@subicura.com


Dockerfile을 관리하는 사람의 이름 또는 이메일 정보를 적습니다. 빌드에 딱히 영향을 주지는 않습니다.

 

COPY


COPY <src>... <dest>
COPY . /usr/src/app


파일이나 디렉토리를 이미지로 복사합니다. 일반적으로 소스를 복사하는 데 사용합니다. target디렉토리가 없다면 자동으로 생성합니다.

Docker CE v17.06.0-ce 부터는 multi-stage 빌드가 포함되어 있습니다.

FROM ~ AS 를 통해 빌드 이미지를 설정할 수 있습니다.

COPY --from= 으로 빌드 이미지를 현재 이미지로 가져올 수 있습니다.

# bulid stage
FROM golang:1.8.3 AS build
MAINTAINER Outsider

ENV VAULT_VERSION=0.7.3

## clone vault source code
WORKDIR /go/src/github.com/hashicorp
RUN git clone https://github.com/hashicorp/vault.git

## build vault
WORKDIR /go/src/github.com/hashicorp/vault
RUN git checkout v"${VAULT_VERSION}"
RUN make bootstrap
RUN make dev

# final stage
FROM debian:jessie
MAINTAINER Outsider

## copy vault from build
COPY --from=build /go/src/github.com/hashicorp/vault/bin/vault /bin/

CMD ["vault", "server", "-dev"]

 

ADD


ADD <src>... <dest>
ADD . /usr/src/app


COPY명령어와 매우 유사하나 몇가지 추가 기능이 있습니다. 

src에 파일 대신 URL을 입력할 수 있고 src에 압축 파일을 입력하는 경우 자동으로 압축을 해제하면서 복사됩니다.

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

  - 예) ADD hello.tar.gz / (압축을 해제하고 tar를 풀어서 추가합니다.)
  - 예) ADD http://zlib.net/zlib-1.2.8.tar.gz / (gzip 압축만 해제한 뒤 tar 파일을 추가합니다. 단 파일 내용은 tar이지만 파일 이름은 zlib-1.2.8.tar.gz처럼 .gz가 붙어있습니다.)

 

RUN


RUN <command>
RUN ["executable", "param1", "param2"]
RUN bundle install


가장 많이 사용하는 구문입니다. 명령어를 그대로 실행합니다. 내부적으로 /bin/sh -c 뒤에 명령어를 실행하는 방식입니다.

 

CMD


CMD ["executable","param1","param2"]
CMD command param1 param2
CMD bundle exec ruby app.rb


도커 컨테이너가 실행되었을 때 실행되는 명령어를 정의합니다.

빌드할 때는 실행되지 않으며 여러 개의 CMD가 존재할 경우 가장 마지막 CMD만 실행됩니다.

한꺼번에 여러 개의 프로그램을 실행하고 싶은 경우에는 run.sh파일을 작성하여 데몬으로 실행하거나,

supervisord나 forego와 같은 여러 개의 프로그램을 실행하는 프로그램을 사용합니다.

 

ENTRYPOINT


ENTRYPOINT ["/usr/sbin/nginx"]

...

$ docker run -t -i test/test:v1 -g "daemon off"

Docker image가 실행될때 실행되어야할 기본 command를 지정한다. 

CMD와 비슷하지만 CMD는 override 가 가능하지만 ENTRYPOINT 는 override 할 수 없다.

대신에 docker run 커맨드로 추가하는 커맨드 들은 ENTRYPOINT instruction에 지정된 커맨드에 옵션으로 추가된다:

 

위의 경우 /usr/sbin/nginx -g "daemon off" 커맨드가 실행된다.

 

CMD 와 ENTRYPOINT를 혼합해서 사용할 수 도 있다. 

CMD 로 지정된 옵션은 만일 docekr run 커멘드로 아무런 커맨드가 추가되지 않으면 default로 추가된다.

 

WORKDIR


WORKDIR /path/to/workdir


RUN, CMD, ADD, COPY등이 이루어질 기본 디렉토리를 설정합니다.

각 명령어의 현재 디렉토리는 한 줄 한 줄마다 초기화되기 때문에 RUN cd /path를 하더라도 다음 명령어에선 다시 위치가 초기화 됩니다. 같은 디렉토리에서 계속 작업하기 위해서 WORKDIR을 사용합니다.

 

EXPOSE


EXPOSE <port> [<port>...]
EXPOSE 4567

도커 컨테이너가 실행되었을 때 요청을 기다리고 있는(Listen) 포트를 지정합니다. 여러개의 포트를 지정할 수 있습니다.

 

VOLUME


VOLUME ["/data"]


컨테이너 외부에 파일시스템을 마운트 할 때 사용합니다. 반드시 지정하지 않아도 마운트 할 수 있지만, 기본적으로 지정하는 것이 좋습니다.

 

ENV


ENV <key> <value>
ENV <key>=<value> ...
ENV DB_URL mysql


컨테이너에서 사용할 환경변수를 지정합니다. 컨테이너를 실행할 때 -e옵션을 사용하면 기존 값을 오버라이딩 하게 됩니다.

 

ARG


ARG env
ARG log_level=debug

docker build 커맨드로 docker image를 빌드할때 설정 할 수 있는 옵션 들을 지정해준다. 예를 들어,

위의 경우 docker build 커맨드로 빌드할때 --build-arg 옵션을 사용하여 env 와 log_level 값을 설정 해줄수 있다.

docker build --build-arg env=prod -t test/test:v1 .

Secrete key나 계정 비밀번호 같은 민감한 정보는 이러한 방식으로 지정하지 않는걸 권한다.

이렇게 지정하면 image에 그대로 남아있기 때문에 image가 노출되면 정보 또한 노출될수 있다.

 

USER


USER nginx

해당 docker image를 실행할 user 를 지정 해준다.

위의 대로 지정하면 docker image가 실행될때 docker container에서 nginx 유저로 image를 실행하게 된다.

유저 이름 뿐만이 아니라 UID 나 GID를 사용할 수 도 있다.


USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

Runtime 때 override 하고 싶으면 -u 옵션을 사용하면 된다. 

USER instruction 으로 지정하지 않으면 default로 root 유저로 image가 실행된다.

 

SHELL


SHELL ["/bin/bash", "-c"]

디포트로 지정되어 있는 shell 타입을 바꿀수 있게 해준다.

Linux의 default shell은 ["/bin/sh", "-c"] 이다.

 


로그 최적화

이미지를 빌드할 때 불필요한 로그는 무시하는게 좋고 패키지 설치시 문서 파일도 생성할 필요가 없습니다.


# before
RUN apt-get -y update

# after
RUN apt-get -y -qq update

● - qq 옵션으로 로그를 출력하지 않게 했습니다. 각종 리눅스 명령어는 보통 quite 옵션이 있으니 적절하게 적용하면 됩니다.


# before
RUN bundle install

# after
RUN bundle install --no-rdoc --no-ri

● -no-doc 과 --no-ri 옵션으로 필요 없는 문서를 생성하지 않아 이미지 용량도 줄이고 빌드 속도도 더 빠르게 했습니다.

 

명령어 최적화

명령어는 비슷한 것끼리 묶어 주는 게 보기도 좋고 레이어 수를 줄이는데 도움이 됩니다.

도커 이미지는 스토리지 엔진에 따라 레이어의 개수가 127개로 제한되어 있는 경우도 있어 너무 많은 명령어는 좋지 않습니다.


# before
RUN apt-get -y -qq update
RUN apt-get -y -qq install ruby

# after
RUN apt-get -y -qq update && \
    apt-get -y -qq install ruby