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 ./
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 시에 덮어 쓸 수 있음.
...ENTRYPOINT ["echo"]CMD ["hello", "world"]...
- 어떤 설정 및 실행이 필요한지에 대한 스크립트로 정리
- ADD 또는 COPY로 스크립트를 이미지로 복사
- ENTRYPOINT를 이 스크립트로 설정
- 이미지를 빌드해 사용
- 스크립트에서 필요한 인자는 docker run 명령어에서 cmd로 entrypoint의 스크립트에 전달
FROM ubuntu:14.04RUN apt-get updateRUN apt-get install apache2 -yADD entrypoint.sh /entrypoint.shRUN chmod +x /entrypoint.shENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
echo $1 $2apachectl -DFOREGROUND
댓글
댓글 쓰기