2020년 9월 7일 월요일

Docker 이미지 만들기 (Dockerfile 작성하기)

 Docker 이미지를 만들기 위해서 간단히 알고 가야 할 것들을 정리해 볼까 한다. 아주 빈번하게 필요한 작업이 아니다 보니 매번 기억을 살려내기 위해서 문서를 찾고 읽고하는 작업을 최소화(?)하기 위해서 간단한 build 명령 사용법과 Dockerfile 명령어들을 정리해 보려고 한다. 나중에 필요한 때가 오면 이 글만 쓰~윽 읽고 바로 작업할 수 있도록...


docker build 명령어 사용


 쓸만한 옵션을 정리해보면 대략 아래 정도가 될 것이다.
$ sudo docker build [OPTIONS] {PATH}
 -f {docker-file}
 -t {repository}:{tag}
{PATH}는 local filesystem 경로이다. Docker 이미지를 생성하는동안 Context가 된다.
'-f'옵션은 생략되면 '{PATH}/Dockerfile'이 사용된다.
'-t'옵션의 {repository}는 'image'이라고도 한다. Docker 이미지는 repository를 통해서 식별되고 배포되기 떄문에 감안하여 이해하도록 하자.

아래는 간단한 명령 예제이다. 참고하도록 하자.
$ sudo docker build .
$ sudo docker build -f /path/to/a/Dockerfile .
$ sudo docker build -t shykes/myapp .
$ sudo docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
$ sudo docker build -t test/myapp .


Dockerfile 명령어


 Dockerfile의 내용은 아래와 같은 포맷으로 된 명령들의 나열이다. 매우 간단하다.
# Comment
INSTRUCTION arguments

FROM

 Dockerfile의 맨 앞에 나오는 명령이다. base가 되는 이미지를 지정한다.
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

FROM ubuntu:latest
FROM node:12
FROM python:3.8-alpine

WORKDIR

컨테이너상에서 작업 디렉토리를 지정한다. 로컬의 경로가 아니라 컨테이너에서의 작업 디렉토리이다.
WORKDIR /path/to/workdir

WORKDIR /usr/app
WORKDIR /usr/local/tomcat

COPY

호스트에 있는 디렉터리나 파일을 Docker 이미지의 파일 시스템으로 복사하기 위해서 사용된다. 상대 경로를 사용하는 경우에는 WORKDIR 명령으로 설정한 경로를 고려하여 지정해야 한다. 경로에 공백문자가 포함된 경우에는 JSON array 형태로 인자를 지정하도록 한다.
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

COPY hom* /mydir/
COPY test.txt relativeDir/
COPY test.txt /absoluteDir/

ADD

COPY 명령과 거의 같지만 압축 파일이나 네트워크 상의 파일들을 이미지에 복사해 넣을 수 있다.
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

ADD hom* /mydir/
ADD test.txt relativeDir/
ADD test.txt /absoluteDir/

RUN

직전까지 생성된 이미지 Layer 위에서 명령을 실행한다. 명령이 실행된 결과는 다음 Layer에 반영될 것이다.
RUN <command>
RUN ["executable", "param1", "param2"]

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
RUN ["/bin/bash", "-c", "echo hello"]

CMD

CMD 명령문은 해당 이미지를 컨테이너로 띄울 때 디폴트로 실행할 커맨드나, ENTRYPOINT 명령문으로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용한다. Dockerfile에 CMD 명령은 하나만 있어야하며 여러 개가 존재하는 경우 마지막 CMD명령만 유효하다.
CMD ["executable","param1","param2"]  (exec form)
CMD ["param1","param2"]  (as default parameters to ENTRYPOINT)
CMD command param1 param2  (shell form)

CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]

ENTRYPOINT

ENTRYPOINT는 컨테이너를 실행할 때 컨테이너에서 실행될 명령을 지정한다. 컨테이너를 마치 실행파일을 실행하는 것처럼 동작하도록 만들기 위해서 사용한다.
ENTRYPOINT ["executable", "param1", "param2"]  (exec form)
ENTRYPOINT command param1 param2  (shell form)

ENTRYPOINT top -b
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

ENV

ENV 명령은 컨테이너상에 환경변수를 설정하기 위해서 사용한다.
ENV <key> <value>
ENV <key>=<value> ...

ENV myName John Doe
ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy

VOLUME

VOLUME 명령은 컨테이너에 mount point를 생성하기 위해서 사용한다. 컨테이너를 실행할 때 제공되는 host의 filesystem을 mount하기 위함이다.
VOLUME ["/var/log/"]
VOLUME /var/log

EXPOSE

EXPOSE 명령은 docker에게 컨테이너가 특정 포트를 listen하고 있음을 알리기 위해서 설정한다. 실제로 포트에 대해서는 아무런 작업도 없고 컨테이너를 실행할 때 '-p' 또는 '-P'옵션으로 실행을 해야한다.
EXPOSE <port> [<port>/<protocol>...]

EXPOSE 80
EXPOSE 80/udp