Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-16 04:51
관리 메뉴

nomad-programmer

[DevOps/Docker] 환경 및 네트워크 설정 (ENV, HEALTHCHECK, STOPSIGNAL, USER, LABEL, EXPOSE, ARG, SHELL, ADD, COPY, VOLUME) 본문

DevOps/Docker

[DevOps/Docker] 환경 및 네트워크 설정 (ENV, HEALTHCHECK, STOPSIGNAL, USER, LABEL, EXPOSE, ARG, SHELL, ADD, COPY, VOLUME)

scii 2020. 12. 1. 22:31

컨테이너를 종료할 때에 송신하는 시그널을 설정하려면 STOPSIGNAL 명령을 사용한다.

STOPSIGNAL [시그널]

STOPSIGNAL 명령에는 시그널 번호 또는 시그널명을 지정할 수 있다.


컨테이너의 헬스 체크 명령 (HEALTHCHECK 명령)

컨테이너 안의 프로세스가 정상적으로 작동하고 있는지를 체크하고 싶을 때는 HEALTHCHECK 명령을 사용한다.

HEALTHCHECK [옵션] CMD 실행할 명령

지정할 수 있는 옵션

옵션 설명 기본값
--interval=n 헬스 체크 간격 30s
--timeout=n 헬스 체크 타임아웃 30s
--retries=N 타임아웃 횟수 3

HEALTHCHECK 명령에서는 Docker에 대해 컨테이너의 상태를 어떻게 확인할지를 설정한다. 예를 들어 5분마다 가동 중인 웹 서버의 메인 페이지(http://localhost)를 3초 안에 표시할 수 있는지 없는지 확인하려면 Dockerfile에 다음과 같이 지정한다.

HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost || exit 1

헬스 체크의 결과는 docker container inspect 명령으로 확인할 수 있다.


환경변수 설정 (ENV 명령)

Dockerfile 안에서 환경변수를 설정하고 싶을 때는 ENV 명령을 사용한다. ENV 명령은 다음 두 서식 중 하나로 기술한다.

ENV [key] [value]

ENV [key]=[value]

환경변수를 지정하는 방법은 다음 두 가지 방법이 있다.

1. key value 형으로 지정하는 경우

단일 환경변수에 하나의 값을 설정한다. 첫 번째 공백 앞을 key로 설정하면 그 이후는 모두 문자열로 취급한다. 공백이나 따옴표와 같은 문자를 포함한 것도 문자로 취급한다.

// key value로 지정하는 경우의 ENV 명령

ENV myName "scii"
ENV myOrder Pasta Pizza
ENV myNickName Procedure

이 명령을 실행하면 명령별로 Docker 이미지를 만든다. 이 예에서는 ENV 명령이 3줄에 걸쳐 있으므로 3개의 Docker 이미지를 겹쳐서 만들게 된다.

2. key=value 로 지정하는 경우

한번에 여러 개의 값을 설정할 때는 환경변수를 key=value 로 지정한다.

// key=value 형식으로 지정하는 경우의 ENV 명령

ENV myName="scii" \
    myOrder=Pasta\ Pizza \
    myNickName=Procedure

여기서는 하나의 ENV 명령으로 여러 개의 값을 설정하므로 만들어지는 Docker 이미지는 하나이다.

변수 앞에 \ (이스케이프 문자) 를 추가하면 이스케이프 처리를 할 수 있다. 예를 들어 \$myName은 $myName 이라는 리터럴로 치환할 수 있다.

ENV 명령으로 지정한 환경변수는 컨테이너 실행 시의 docker container run 명령의 --env 옵션을 사용하면 변경할 수 있다.


작업 디렉토리 지정 (WORKDIR 명령)

Dockerfile에서 정의한 명령을 실행하기 위한 작업용 디렉토리를 지정하려면 WORKDIR 명령을 설정한다.

WORKDIR [작업 디렉토리 경로]

WORKDIR 명령은 Dockerfile에 쓰여 있는 다음과 같은 명령을 실행하기 위한 작업용 디렉토리를 지정한다.

  • RUN 명령
  • CMD 명령
  • ENTRYPOINT 명령
  • COPY 명령
  • ADD 명령

만일 지정한 디렉토리가 존재하지 않으면 새로 작성한다. 또한 WORKDIR 명령은 Dockerfile 안에서 여러 번 사용할 수 있다. 상대 경로를 지정한 경우는 이전 WORKDIR 명령의 경로에 대한 상대 경로가 된다. 예를 들어 다음과 같이 지정하면 마지막 줄 실행 후 /first/second/third 가 출력된다.

// 절대경로/상대경로를 사용한 WORKDIR 명령

WORKDIR /first
WORKDIR second
WORKDIR third
RUN ["pwd"]

WORKDIR 명령에는 ENV 명령에서 지정한 환경변수를 사용할 수 있다. 예를 들어 Dockerfile에서 다음과 같이 지정하면 마지막 줄 실행 후 /first/second 가 출력된다.

// WORKDIR 명령으로 환경변수를 사용한 예

ENV DIRPATH /first
ENV DIRNAME second

// 또는
ENV DIRPATH="/first" \
    DIRNAME="second"

WORKDIR $DIRPATH/$DIRNAME
RUN ["pwd"]

사용자 지정 (USER 명령)

이미지 실행이나 Dockerfile의 다음과 같은 명령을 실행하기 위한 사용자를 지정할 때는 USER 명령을 사용한다.

  • RUN 명령
  • CMD 명령
  • ENTRYPOINT 명령
USER [사용자명/UID]

USER 명령에서 지정하는 사용자는 RUN 명령으로 미리 작성해 놓을 필요가 있다는 점에 주의해야 한다.

예를 들어 다음의 예에서는 RUN 명령으로 scii라는 사용자를 작성한 후, USER 명령에서 scii를 설정하고 두 번째 RUN 명령을 scii라는 계정에서 실행하고 있다.

// USER 명령의 예

RUN ["adduser", "scii"]
RUN ["whoami"]
USER scii
RUN ["whoami"]

이 Dockerfile을 빌드하면 첫 번째 whoami 명령은 root이지만, 두 번째 whoami 명령은 USER 명령으로 지정한 scii 가 되어 있다. 또한 해당 컨테이너의 bash 쉘에 접근하면 마찬가지로 scii로 로그인 된다.


라벨 지정 (LABEL 명령)

이미지에 버전 정보나 작성자 정보, 코멘트 등과 같은 정보를 제공할 때는 LABEL 명령을 사용한다.

LABEL <키 명>=<값>

다음은 LABEL 명령을 사용하여 이미지에 정보를 설정하는 예이다.

LABEL maintainer "scii<abc55@gmail.com>"
LABEL title="web app"
LABEL version="1.0"
LABEL description="This image is Web Application Server"

이 명령을 바탕으로 Dockerfile을 빌드하여 생성된 sample이라는 이름의 이미지의 상세 정보를 확인하면, 다음과 같이 LABEL 명령으로 지정한 정보가 설정되어 있는 것을 알 수 있다.

// 이미지의 상세 정보

$ docker image inspect --format="{{ .Config.Labels }}" label-sample

map[description:This image is Web Application Server maintainer:scii<abc55@gmail.com> title:web app version:1.0]
구 버전(1.13 이전)의 Docker에서는 Dockerfile의 작성자를 기술할 때 MAINTAINER 명령을 사용했었지만, 이 명령은 현재 권장하지 않으므로 LABEL 명령을 사용해야 한다.

포트 설정 (EXPOSE 명령)

컨테이너의 공개 포트 번호를 지정할 때는 EXPOSE 명령을 사용한다.

EXPOSE <포트 번호>

EXPOSE 명령은 Docker에게 실행 중인 컨테이너가 listen하고 있는 네트워크를 알려준다. 또한 docker container run 명령의 -p 옵션을 사용할 때 어떤 포트를 호스트에 공개할지를 정의한다.

예를 들어 8080 포트를 공개하기 위한 EXPOSE 명령은 다음과 같다.

EXPOSE 8080

Dockerfile 안에서의 변수 설정 (ARG 명령)

Dockerfile 안에서 사용할 변수를 정의할 때는 ARG 명령을 사용한다. 이 ARG 명령을 사용하면 변수의 값에 따라 생성되는 이미지의 내용을 바꿀 수 있다.

환경변수인 ENV와는 달리 이 변수는 Dockerfile 안에서만 사용할 수 있다. 즉 ENV는 컨테이너를 생성했을 때 설정한 해당 변수가 컨테이너안에서도 사용할 수 있도록 환경변수가 등록되어있지만 ARG는 오로지 Dockerfile에서만 유효하다.
ARG <이름>[=기본값]

예를 들어 다음과 같이 하면 ARG 명령으로 'YOURNAME' 이라는 변수를 정의한 Dockerfile을 작성할 수 있다.

# 변수의 정의
ARG YOURNAME="scii"
RUN echo $YOURNAME

이 Dockerfile을 빌드할 때 --build-arg 옵션을 붙여 ARG 명령에서 지정한 'YOURNAME' 에 'scii' 라는 값을 설정하고 다음과 같이 명령을 실행한다.

// ARG 명령 실행

$ docker build . --build-arg YOURNAME=scii5

...
Step 6/7 : ARG YOURNAME="scii"
 ---> Running in e795379f1d13
Removing intermediate container e795379f1d13
 ---> 0087f8156620
Step 7/7 : RUN echo $YOURNAME
 ---> Running in de167372517f
scii5
...

로그를 확인하면 변수에 값이 설정되어 Dockerfile 안에서 이용할 수 있다는 것을 알 수 있다.


기본 쉘 설정 (SHELL 명령)

쉘 형식으로 명령을 실행할 때 기본 쉘을 설정하려면 SHELL 명령을 사용한다. SHELL 명령을 지정하지 않았을 떄 Linux의 기본 쉘은 ["/bin/sh", "-c"], Windows는 ["cmd", "/S", "/C"] 이 된다.

SHELL ["쉘의 경로", "파라미터"]

다음은 기본 쉘을 /bin/bash 로 변경하여 RUN 명령을 실행한 예이다.

# 기본 쉘 지정
SHELL ["/bin/bash", "-c"]

# RUN 명령 실행
RUN echo hello

SHELL 명령을 지정하면 그 쉘은 그 이후에 Dockerfile 안에서 Shell 형식으로 지정한 RUN 명령이나 CMD 명령, ENTRYPOINT 명령에서 유효해진다.


파일 및 디렉토리 추가 (ADD 명령)

이미지에 호스트상의 파일이나 디렉토리를 추가할 때는 ADD 명령을 사용한다.

ADD <호스트의 파일 경로> <Docker 이미지의 파일 경로>

ADD ["<호스트의 파일 경로>" "<Docker 이미지의 파일 경로>"]

ADD 명령은 호스트상의 파일이나 디렉토리, 원격 파일을 Docker 이미지 안으로 복사한다. 예를 들어 호스트상의 index.html 파일을 이미지 안의 /docker_dir/ 에 추가하려면 다음과 같이 지정한다.

ADD index.html /docker_dir/

추가하고 싶은 호스트의 파일 경로에는 Dockerfile의 디렉토리 내부를 지정하기 바란다.

호스트의 파일 경로에는 와일드카드와 Go 언어의 filepath.Match 룰과 일치하는 패턴을 사용할 수 있다.
// ADD 명령에 사용하는 패턴 예

# [ind]로 시작하는 모든 파일을 추가
ADD ind* /docker_dir/

# [index]+임의의 한 문자 롤에 해당하는 파일을 추가
ADD index?.txt /docker_dir/

Docker 이미지 안의 파일은 절대 경로로 지정하거나 WORKDIR 명령에서 지정한 디렉토리를 기점으로 한 경로로 지정한다. 예를 들어 WORKDIR 명령에서 /docker_dir 을 지정하고, /docker_dir 안의 web이라는 디렉토리에 index.html 을 복사하려면 다음의 명령을 실행한다.

WORKDIR /docker_dir
ADD index.html web/

생성된 이미지를 바탕으로 컨테이너를 시작하고 확인하면 /docker_dir/web 아래에 index.html 파일이 추가되어 있는 것을 알 수 있다.

$ docker container run -it --rm ls -l /docker_dir/web

-rw-rw-r-- 1 root root 0 Dec  1 15:20 index.html

이미지에 추가하고 싶은 파일이 원격 파일 URL인 경우, 추가한 파일은 퍼미션이 600 (사용자만 읽기 쓰기 가능) 이 된다. 만일 취득한 원격 파일이 HTTP Last-Modified 헤더를 갖고 있다면 추가된 파일에서 mtime의 값으로 사용된다.

또한 ADD 명령은 인증을 지원하지 않기 때문에 원격 파일의 다운로드 인증이 필요한 경우는 RUN 명령에서 wget 명령이나 curl 명령을 사용해야 한다.

HTTP Last-Modified 헤더
HTTP에서 컨텐츠의 데이터를 마지막으로 갱신한 날짜 (Last-Modified)의 타임스탬프를 말한다.

다음의 명령을 실행하면 http://www.test.com/index.php 를 다운로드하여 Docker 이미지 안의 /docker_dir/web/index.php로 퍼미션이 600인 파일이 추가된다. 

// ADD 명령에서 원격 파일 추가

ADD http://www.test.com/index.php /docker_dir/web/
  • 이미지 안의 파일 지정이 파일일 때는 URL로부터 파일을 다운로드하여 지정한 파일명을 추가한다.
  • 이미지 안의 파일 지정이 디렉토리일 때는 파일명은 URL로 지정한 것이 된다.

호스트의 파일이 tar 아카이브거나 압축 포맷(gzip, bzip2 등) 일 때는 디렉토리로 압축을 풀어준다. 단, 원격 URL로부터 다운로드한 리소스는 압축이 풀리지 않으므로 주의해야 한다.


파일 복사 (COPY 명령)

이미지에 호스트상의 파일이나 디렉토리를 복사할 때는 COPY 명령을 사용한다.

COPY <호스트의 파일 경로> <Docker 이미지의 파일 경로>

COPY ["<호스트의 파일 경로>" "<Docker 이미지의 파일 경로>"]

ADD 명령과 COPY 명령은 매우 비슷하다. ADD 명령은 원격 파일의 다운로드나 아카이브의 압축 해제 등과 같은 기능을 갖고 있지만, COPY 명령은 호스트상의 파일을 이미지 안으로 '복사하는' 처리만 한다. 이 때문에 단순히 이미지 안에 파일을 배치하기만 하고 싶을 때는 COPY 명령을 사용한다.

COPY 명령의 구문은 ADD 명령과 똑같다.


Dockerfile의 저장 위치

Dockerfile로부터 이미지를 만들 때 docker build 명령은 Dockerfile을 포함하는 디렉토리(서브 디렉토리를 포함한다)를 모두 Docker 데몬으로 전송한다.

예를 들어 시스템의 루트 디렉토리를 소스 저장소로 사용한 경우는 루트 디렉토리의 모든 컨텐츠를 Docker 데몬으로 전송하기 때문에 처리가 느려진다.

그래서 Dockerfile의 저장 위치는 빈 디렉토리를 만들고 거기에 Dockerfile을 놓아두고 이미지를 작성하는 방법을 권장한다.

Docker의 빌드에 필요 없는 파일은 Dockerfile과 똑같은 디렉토리에 두지 않도록 주의하는 것이 좋다.

볼륨 마운트 (VOLUME 명령)

이미지에 볼륨을 할당하려면 VOLUME 명령을 사용한다.

VOLUME ["/마운트 포인트"]

VOLUME 명령은 지정한 이름의 마운트 포인트를 작성하고, 호스트나 그 외 다른 컨테이너로부터 볼륨의 외부 마운트를 수행한다. 설정할 수 있는 값은 VOLUME ["/var/log/"] 와 같은 JSON 배열, 또는 VOLUME /var/log 나 VOLUME /var/log /var/db 와 같은 여러 개의 인수로 된 문자열을 지정할 수 있다.

컨테이너는 영구 데이터를 저장하는 데는 적합하지 않다. 그래서 영구 저장이 필요한 데이터는 컨테이너 밖의 스토리지에 저장하는 것이 좋다.

영구 데이터는 Docker의 호스트 머신상의 볼륨에 마운트하거나 공유 스토리지에 볼륨으로 마운트 하는 것이 가능하다.

Comments