Dockerfile

기본적인 사용법을 알았으면, 그 다음은 Dockerfile 작성이 Docker 사용의 50% 이상은 되는 것 같다.

자세한 건 공식 문서를 참조하시길.

Dockerfile이 뭐요?

Dockerfile은 Docker 이미지를 만들기 위한 스크립트이다. 가장 간단하게는 Dockerfile 하나만 있으면 Docker 이미지를 만들 수 있으며, 그 외에 추가적인 데이터(일반적으로는 사용자 설정 데이터; configuration 파일)가 있으면 Docker 이미지를 만들 수 있다.

기본적으로 거의 다 메타 정보만 포함하고 있기 때문에, Git으로 관리하기가 아주 좋다.

유명 벤더들의 Dockerfile 관리 예시

Dockerfile 사용법

Dockerfile이 있다는 가정 하에, 이미지를 만드려면 어떻게 할까?

바로 docker build를 하면 된다. 이 역시 자세한 문법은 공식 문서를 참조하면 된다.

대개 다음과 같이 사용한다.

kesuskim@docker-test:~/workspace$ ls -alh
total 12K
drwxrwxr-x 2 kesuskim kesuskim 4.0K Apr 23 12:56 .
drwxr-xr-x 8 kesuskim kesuskim 4.0K Apr 23 13:21 ..
-rw-rw-r-- 1 kesuskim kesuskim  550 Apr 23 12:56 Dockerfile

kesuskim@docker-test:~/workspace$ docker build -t kesuskim/drools-wb:latest ./

Dockerfile 문법

주석 (Comments)

주석은 # 으로 달면 된다.

# 이게 주석이오.
# 이 값은 읽히지 않음!
FROM nginx:alpine
~~

.dockerignore 파일

Git 에서의 .gitignore 파일처럼, Docker에서는 .dockerignore 파일도 존재한다.

.gitignore 파일의 목적과 동일한 목적을 위해 존재하며, 동작도 거의 유사하다.

# .dockerignore
# 주석
*/temp*
*/*/temp*
temp?

GLOB 패턴도 받아들이므로, 필요하면 사용하시면 된다.

자세한 문서 « 참조가 필요하신 분들에게..

FROM

기존의 레이어에서부터 시작할 수 있는 녀석.

대체 무슨 말이냐면, 어떠한 시스템, 또는 프로그램을 실행하기 위해 처음부터 운영체제를 설치할 필요가 없다는 말이다! (헉) 다른 사람이 해 놓은 것에서부터 시작할 수 있다.

공식 문서에는 ‘베이스 이미지’ 라고 표현되어 있는데, 적합한 표현인 것 같지만 처음 보시는 분에게는 잘 이해가 안될 수도 있으니 예시를 몇 개 보도록 하자.

  • htop을 실행시키는 이미지 (실제로 이런 짓은 하지 말자. 굉장히 무겁고 비 효율적이다. 예시를 위해서..)
FROM ubuntu:latest

RUN apt-get update -y
RUN apt-get install htop -y

CMD ["htop"]
FROM ubuntu:14.04
MAINTAINER Foo Bar <[email protected]>

RUN apt-get update
RUN apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN chown -R www-data:www-data /var/lib/nginx

VOLUME ["/data", "/etc/nginx/site-enabled", "/var/log/nginx"]

WORKDIR /etc/nginx

CMD ["nginx"]

EXPOSE 80
EXPOSE 443
  • 아무것도 없는 것으로부터(No base image!) 시작하는 예제. 이에 대해 자세한 예시는 공식 문서를 확인하시라
FROM scratch
ADD hello /
CMD ["/hello"]

(hello 라는 실행 파일이 있다는 가정 하에 위의 스크립트가 동작함!)


FROM에는 3가지의 문법이 있다고 한다.

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

위에서 보았던 것처럼, ubuntu:latest 나 ubuntu:14.04는 태그 값을 의미하며, 이는 Dockerhub 에 관련 이미지를 검색하면 알 수 있다.

digest는 각각의 이미지의 해시 값이다. 자세한 설명은 공식 문서의 스크린 샷으로 대체하겠음!

Docker_Digest

RUN

RUN은 Dockerfile이 이미지를 생성하는 과정에서 실행될 명령어를 지칭한다.

RUN에는 2가지의 문법이 있다고 한다.

  1. 일반적으로 Shell 커맨드 처럼 사용하는 방법
RUN <command>
  1. exec 사용하듯 사용하는 방법
RUN ["executable", "param1", "param2", ...]

2번의 경우, 사용하려면 PATH가 확정되어야 한다는 사실을 잊지 말자!

CMD

CMD는 Dockerfile이 이미지로 생성된 이후, 컨테이너로 만들어지며 실행되는 ‘첫 명령어’ 를 지칭한다. Dockerfile 내부에 단 하나의 CMD 명령어만 존재한다.

CMD에는 3가지의 문법이 있다고 한다.

  1. 일반적으로 선호되는 방법: exec 사용하듯 사용하는 방법
CMD ["executable", "param1", "param2", ...]
  1. ENTRYPOINT 명령어의 기본 파라미터로 넘겨주는 방법
CMD ["param1", "param2", ...]
  1. Shell 커맨드 처럼 사용하는 방법
CMD <command> <param1> <param2> ...

단 하나의 CMD만 동작해야 한다는 사실을 기억하라. 만일 여러 개의 CMD 명령어를 사용하면, 맨 마지막에 있는 CMD만 동작할 것이다.

ENTRYPOINT

ENTRYPOINT는 컨테이너를 실행시킬 때, 어떤 프로그램이 실행되야 하는지에 대한 부분을 조정할 수 있다.

이는 마치 ubuntu 라는 리눅스 운영체제 안에서, 즉 리눅스라는 프로그램 자체 안에서 여러 개의 프로그램을 실행시킬 수 있듯이, 그것을 조정할 수 있는 녀석이다.

ENTRYPOINT에는 2가지의 문법이 있다고 한다.

  1. 일반적으로 선호되는 방법: exec 사용하듯 사용하는 방법
ENTRYPOINT ["executable", "param1", "param2", ...]
  1. Shell 커맨드 처럼 사용하는 방법
ENTRYPOINT <command> <param1> <param2> ...

ENTRYPOINT와 CMD 간의 관계

ENTRYPOINT 와 CMD 둘 다 컨테이너가 실행될 때에 어떠한 명령어가 실행되야 할 지를 정의한다. 두 명령의 관계를 나타낸 몇 가지 규칙이 있는데, 다음과 같다.

  1. Dockerfile에는 최소한 둘(ENTRYPOINT, CMD) 중 하나의 명령을 가지고 있어야 함
  2. ENTRYPOINT는 컨테이너를 실행 가능한 형태로 만들때(데몬 프로세스처럼) 사용되어야 함
  3. CMD는 ENTRYPOINT가 실행 가능한 형태의 컨테이너로 동작할 때에 기본 인자 설정 값으로 사용되거나, 컨테이너 내에서 임시로 명령을 내릴 때에 사용되어야 함
  4. CMD는 컨테이너가 실행될 때에 입력 받은 인자에 의해 무시됨

WORKDIR

WORKDIR는 Linux에 익숙하신 분들에게는 다 알거라고 생각하는, 현재 경로를 나타낸다. 좀더 정확히 지칭하면, 생성할 컨테이너 내의 현재 경로를 나타낸다. 대개 컨테이너가 실행되기 이전에 수행할 어떠한 작업들을 하기 이전에, base directory 같은 개념이 되는 경로를 지칭해준다.

WORKDIR /usr/share/nginx/html

COPY

COPY는 이미지 생성 시, 호스트의 파일을 이미지 내부로 복사할 수 있는 명령어이다.

대개 설정 파일 등을 복사할 때에 사용된다.

COPY에는 2가지의 문법이 있다고 한다.

COPY <호스트에 있는 파일> <이미지 내부의 파일>
COPY ["<호스트에 있는 파일>", ..., "<이미지 내부의 파일>"]

정확한 문자열 대신에 간단한 정규식도 받기 때문에(GLOB 패턴도), 여러 개의 파일을 복사하는 것도 가능하다.

COPY sites-enabled/* /etc/nginx/sites-enabled/

주의할 점이 있는데, 호스트에 있는 파일을 복사할 때에는, Dockerfile 파일이 존재하는 경로보다 하부 경로에 위치하는 파일만 복사 가능하다. 즉, COPY ../standalone.xml /opt/wildfly/conf/standalone.xml 이런 식의, 부모 경로(..) 참조는 되지 않는다는 말이다. 따라서, Dockerfile로 작업할 때에 별도의 디렉토리를 만들어서, 그 디렉토리 내부에 새로 만들어 낼 이미지의 필요한 파일들을 전부 다 넣어놓고, 그 디렉토리를 git으로 관리하면 아주 좋은 모습이 된다!

USER

USER는 컨테이너 내에서 명령들이 실행될 때에 필요한 사용자를 설정해주는 명령이다.

USER gogs

VOLUME

VOLUME은 실행 중인 컨테이너 내의 디렉토리와 호스트의 디렉토리를 연결시켜주는 (mount point!), 또는 공유할 수 있는? 명령어이다.

기본적으로 Dockerfile 내의 VOLUME 명령어에서 지정한 이미지 내의 디렉토리를, docker를 컨테이너로 실행시킬 때에 직접 지정해 준 인자 값으로 연결시켜준다.

...
VOLUME /usr/share/nginx/html
...
docker run -v /host/working/directory:/usr/share/nginx/html 어떤이미지

이런 식으로!


---

이 정도면 대략적으로 Dockerfile 작성 시 자주 사용되는 명령어들의 전부 인 것 같다. 나머지는 공식 문서에서 찾아보면서 할 수 있다. :)