Dockerfile 작성

Dockerfile 작성

  • 한줄에 하나의 명령어
  • 명령어 뒤 옵션
  • 명령어는 위에서 아래로 한 줄씩 차례대로 실행
  • 명령어 대소문자 구분 없음
  • 빌드 context는 Dockerfile이 위치한 디렉터리

ex)

FROM ubuntu:14.04

MAINTAINER john123

LABEL "purpose"="practice"

RUN apt-get update

RUN apt-get install apache2 -y

ADD test.html /var/www/html

WORKDIR /var/www/html

RUN ["/bin/bash", "-c", "echo hello >> test2.html"]

EXPOSE 80

CMD apachectl -DFOREGROUND


FROM

  • 베이스 이미지(docker run에 사용하는 이름)

MAINTAINER

  • 이미지를 생성한 개발자 정보(1.13.0 이전 버전에서만. 이후는 LABEL로)
  • = LABEL maintainer "alicek106 <alicek105@naver.com>"

LABEL

  • 이미지 메타데이터.
  • 키:값 형태.
  • docker inspect로 조회 가능

RUN

  • 컨테이너 내부에서 명령어 실행.
  • = RUN ["실행 가능한 파일", "명령줄 인자 1", "명령줄 인자 2", ...]

ADD

  • 파일을 이미지에 추가.
  • 추가할 파일은 Dockerfile과 같은 디렉터리(context)에서 가져옴.
  • = ADD ["추가할 파일 1", "추가할 파일 2", ... "컨테이너에 추가할 위치"]

WORKDIR

  • cd와 같음.

EXPOSE

  • 컨테이너의 포트 설정. 반드시 호스트 포트와 바인딩 되는 것은 아님.

CMD

  • 컨테이너 시작시 실행할 명령어.
  • Dockerfile에 한번만 사용 가능.
  • run으로 컨테이너 실행할 때 명령어를 주면 CMD의 명령은 덮힌다.
  • 또한, 이미지 내장 커맨드는 CMD 명령에 의해 덮힌다.
  • = CMD ["실행 파일", "명령줄 인자 1", "명령줄 인자 2", ...]


Dockerfile 빌드

$> docker build -t test-image:0.0 ./

-> docker build [-f {도커파일명}] -t {생성 이미지명}:{태그} {dockerfile 위치}

-t 없으면 16진수 형태의 이름으로 이미지 생성


이미지 실행

$> docker run -d -P --name myserver mybuild:0.0

-P : EXPOSE의 모든 포트를 호스트에 연결(호스트의 어떤 포트와 연결됐는지 확인 필수)


포트 확인

$> docker ps

or

$> docker port {컨테이너명}


Docker Build Context

  • 도커 빌드에서 Dockerfile 위치로 지정한 디렉터리.
  • 하위 모두 포함
  • URL로 지정 가능. ex) Git hub

ex) 아래 빨간색 부분(현재 디렉터리)

 $> docker build -t test-image:0.0 ./


컨텍스트 제외하기
Dockerfile .dockerignore 파일 작성

$> vi .dockerignore

test2.html   # test2.html 제외

*.html         # html 확장자의 모든 파일 제외

*/*.html      # 하위 1 depth 디렉터리 내의 html 확장자의 모든 파일 제외

test.htm?     # 한 글자 와일드(=?) 처리하여 파일 제외

!abcd.html   # abcd.html은 제외하지 않음 


Docker Build Cache

  • 이미지 빌드는 캐싱 됨.
  • 중간에 빌드 에러나면 다시 빌드 할때 캐시를 사용.
  • 캐시 삭제는 docker images에서 <none>:<none>으로 돼어 있으니 이를 삭제.
  • "RUN git clone" 이후에 빌드 에러가 난 경우 재빌드 하면 캐시를 사용하니 중간에 소스 변경이 있어 다시 clone해야하면 반드시 캐시 날릴 것.


캐시 사용하지 않고 빌드

$> docker build --no-cache -t mybuild:0.0 ./


특정 캐시 사용

$> docker build --cache-from nginx -t my_extend_nginx:0.0 ./


Multi-Stage Build

여러 개의 이미지(FROM)를 이용해서 최종 결과물의 사이즈를 줄일 수 있다.

ex) 하나의 Dockerfile

FROM golang

ADD main.go /root

WORKDIR /root

RUN go build -o /root/mainApp /root/main.go


FROM golang

ADD main2.go /root

WORKDIR /root

RUN go build -o /root/mainApp2 /root/main.go


FROM alpine:latest

WORKDIR /root

COPY --from=0 /root/mainApp .

COPY --from=1 /root/mainApp . 


--from은 맨 위부터 차례대로 이미지(최종상태)를 가리킨다.

또한 특정 단계를 번호가 아닌 alias를 줄 수 도 있다.

FROM golang as builder

...

COPY --from=builder /root/mainApp .


기타 Dockerfile 명령어

1) ENV

  • Dockerfile에서 사용할 환경 변수 지정
  • ${환경변수명} 또는 $환경변수명 으로 사용 가능
  • 이미지에도 저장됨으로 컨테이너 생성하면 이 환경 변수 사용 가능.
  • docker run 시에 -e 옵션으로 덮어 쓸 수 있다.

# vi Dockerfile

FROM ubuntu:14.04

ENV test /home

WORKDIR $test

RUN touch $test/mytouchfile

cf)

${env:-value} : env 값이 설정되어 있지 않으면 value로 설정.

${env:+value} : env 값이 설정되어 있으면 value로 설정 아니면 빈 문자열.


2) VOLUME

호스트와 공유할 컨테이너 내부의 디렉터리 설정.

["/home/dir", "home/dir2", ...]의 JSON 배열 형식으로 지정 가능.

# vi Dockerfile

FROM ubuntu:14.04

RUN mkdir /home/volume

RUN echo test >> /home/volume/testfile

VOLUME /home/volume

cf) 볼륨 확인

$> docker volume ls


3) ARG

  • docker build에서 argument 전달할 때 사용.
  • default 값 설정 가능

# vi Dockerfile

FROM ubuntu:14.04

ARG my_arg

ARG my_arg_2=value2

RUN touch ${my_arg}/mytouch


4) USER

  • 컨테이너 내에서 사용될 계정의 이름이나 UID를 설정.
  • USER로 설정된 아래 명령어는 해당 USER 권한으로 실행 됨.

# vi Dockerfile

...

RUN groupadd -r author && useradd -r -g author alicek106

USER alicek106

...

cf)

  • 컨테이너는 기본적으로 root 사용자.
  • 그러니 호스트와 디렉터리 공유를 할 시에 위험 할 수 있음.
  • docker run --user 옵션이 있지만 되도록 이미지 자체에 사용자 설정을 해서 사용하도록


5) ONBUILD

빌드된 이미지 기반으로 다른 이미지가 Dockerfile로 생성될 때 실행할 명령어를 지정.

아래 

# vi Dockerfile

FROM ubuntu:14.04

RUN echo "this is onbuild test"

ONBUILD RUN echo "onbuild!" >> /onbuild_file

$> docker build ./ -t onbuild_test:0.0

확인 -> onbuild_file 없음

$> docker run -it --rm onbuild_test:0.0 ls /


# vi Dockerfile2

FROM onbuild_test:0.0

RUN echo "this is child image!"

$> docker build -f Dockerfile2 ./ -t onbuild_test:0.1

확인 -> onbuild_file 생성 확인

$> docker run -it --rm onbuild_test:0.1 ls /


6) STOPSIGNAL

컨테이너 정지될 때 사용할 시스템 콜 종류 지정

default는 SIGTERM

# vi Dockerfile

FROM ubuntu:14.04

STOPSIGNAL SIGKILL


7) HEALTHCHECK

  • 컨테이너 내부의 어플리케이션 상태 체크.
  • curl을 사용하기 때문에 curl 설치 필요.

# vi Dockerfile

FROM nginx

RUN apt-get update -y && apt-get install curl -y

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

상태 확인

$> docker ps

CONTAINER ID   ...   STATUS    ...

          ...                  ...   Up 9 minutes (healty)  ... 


8) SHELL

  • 기본 shell: linux -> /bin/sh -c, windows -> cmd /S /C
  • shell을 따로 지정하고자 할때 사용.

# vi Dockerfile

FROM node

RUN echo hello, node!

SHELL ["/usr/local/bin/node"]

RUN -v

RUN -v : 빌드시 node 버전 출력


9) COPY

  • 사용법은 ADD와 동일
  • 차이점은 COPY는  로컬 파일만 가능하고 ADD는 url, tar 파일에서도 파일 추가 가능.
  • 즉, COPY의 기능이 ADD에 포함됨.

ADD의 경우

  • url로 추가 : ADD https://raw.githubusercontent.com/abcd/test.html /home
  • tar 풀어서 추가 : ADD test.tar /home

10) ENTRYPOINT

  • CMD와 같지만 entrypoint가 설정되면 커맨드(CMD)를 인자로 받음.
  • 즉, 커맨드를 인자로 한 스크립트 역할을 한다.
  • 그래서 컨테이너 실행시 실행할 스크립트를 작성할 수 있다.
  • Dockerfile에 지정하더라도 docker run 시에 덮어 쓸 수 있음.
# vi Dockerfile
...
ENTRYPOINT ["echo"]
CMD ["hello", "world"]
...
ex)
$> docker run -it --name no_entrypoint ubuntu:14.04 /bin/bash
-> bash가 실행 된다.
$> docker run -it --entrypoint="echo" --name yes_entrypoint ubuntu:14.04 /bin/bash
-> echo /bin/bash 가 실행 된다.


cf) entrypoint를 이용한 컨테이너 실행
  1. 어떤 설정 및 실행이 필요한지에 대한 스크립트로 정리
  2. ADD 또는 COPY로 스크립트를 이미지로 복사
  3. ENTRYPOINT를 이 스크립트로 설정
  4. 이미지를 빌드해 사용
  5. 스크립트에서 필요한 인자는 docker run 명령어에서 cmd로 entrypoint의 스크립트에 전달
ex)
# vi Dockerfile

FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install apache2 -y
ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

# vi entrypoint.sh
echo $1 $2
apachectl -DFOREGROUND
$> docker build -t ./ entrypoint_image:0.0
$> docker run -d --name entrypoint_apache_server entrypoint_image:0.0 first second
$> docker logs entrypoint_apache_server



댓글

이 블로그의 인기 게시물

[Protocol] WIEGAND 통신

Orange for Oracle에서 한글 깨짐 해결책

[URL] 대소문자를 구분하나?