[Docker] Dockerfile 구성 및 빌드
Dockerfile 구성 및 빌드
Dockerfile은 Docker 상에서 작동시킬 컨테이너의 구성 정보를 기술하기 위한 파일docker build
명령은 Dockerfile에 기술된 구성 정보를 바탕으로 Docker 이미지를 작성
Visual Studio Code를 사용한 Dockerfile
vscode-docker
: Dockerfile을 작성하고 CTRL + Space Bar 를 누르면 스니펫(snippet)이 표시됨docker-compose.yml
파일도 지원함
Dockerfile의 기본 명령
명령 | 설명 |
---|---|
FROM | 베이스 이미지 지정 |
RUN | 명령 실행 |
CMD | 컨테이너 실행 명령 |
LABEL | 라벨 설정 |
EXPOSE | 포트 익스포트 |
ENV | 환경변수 |
ADD | 파일/디렉토리 추가 |
COPY | 파일 복사 |
ENTRYPOINT | 컨테이너 실행 명령 |
VOLUME | 볼륨 마운트 |
USER | 사용자 지정 |
WORKDIR | 작업 디렉토리 |
ARG | Dockerfile 안의 변수 |
ONBUILD | 빌드 완료 후 실행되는 명령 |
STOPSIGNAL | 시스템 콜 시그널 설정 |
HEALTHCHECK | 컨테이너의 헬스 체크 |
SHELL | 기본 쉘 설정 |
Dockerfile 주석 서식1
# 이것은 주석입니다
명령 인수
Dockerfile 주석 서식2
# 이것은 주석입니다
명령 인수 # 이것도 주석입니다
Dockerfile 작성
Dockerfile에는 'Docker 컨테이너를 어떤 Docker 이미지로부터 생성할지' 정보를 반드시 기술 해야 함
이 이미지를 베이스 이미지 라고 함
FROM 명령
베이스 이미지 정보 기술
FROM [이미지명]
FROM [이미지명]:[태그명]
FROM [이미지명]:[다이제스트]
zulu-open-zdk:13을 베이스 이미지로 한 Dockerfile
태그명을 생략하면 베이스 이미지의 최신 버전(latest)이 적용됨
이미지명이나 태그명은 작성자가 임의의 값을 붙일 수 있으므로 Dockerfile을 수정해도 똑같은 이름으로 몇 번이든 이미지를 만들 수 있음
# 베이스 이미지 설정
FROM azul/zulu-openjdk:13
다이제스트 확인
이미지를 고유하게 특정할 때는 다이제스트를 이용함
다이제스트는 Docker Hub에 업로드하면 자동으로 부여되는 식별자를 말함
이 다이제스트는 고유한 식별자이기 때문에 이미지를 고유하게 지정할 수 있음
docker image ls --digests azul/zulu-openjdk
다이제스트를 지정한 Dockerfile
FROM azul/zulu-openjdk@sha256:12945255963826437ca7c52f2ffe45b6862b24b4b73dfb74af05d461607f75ac
Dockerfile의 빌드와 이미지 레이어
Dockerfile로 부터 이미지를 생성하려면 docker build
명령을 사용
docker build 명령의 서식
docker build -t [생성할 이미지명] : [태그명] [Dockerfile의 위치]
docker build 명령의 실행 예
Dockerfile로 부터 sample 이라는 이미지를 작성 태그명은 1.0
Dockerfile의 저장 위치를 절대 경로로 지정 /home/docker/sample
상대경로로 지정할 수도 있음
docker build -t sample:1.0 /home/docker/sample
이미지 확인
docker image ls
새로운 이미지의 작성 예
이름은 다르지만 동일한 이미지
docker build -t sample:2.0 /home/docker/sample
파일명을 지정한 docker build 명령 실행
현재 디렉토리에 있는 Dockerfile.base라는 이름의 파일을 -f
옵션으로 지정하여 build
파일명이 Dockerfile 이외의 이름인 경우는 Docker Hub에서 이미지의 자동 생성 기능을 사용할 수 없음
docker build -t sample -f Dockerfile.base .
표준 입력에서의 빌드
표준 입력을 경유하여 Dockerfile을 지정하여 빌드를 할 수도 있음
표준 입력의 내용ㅇ로서 Dockerfile의 내용을 docker build
명령의 인수로 전달하므로 -
(하이픈)을 지정함
docker build - < Dockerfile
압축 아카이브에 의한 표준 입력에서의 빌드
빌드에 필요한 파일을 포함시킬 수 없기 때문에 Dockerfile과 빌드에 필요한 파일을 tar
로 모아두고 표준 입력에서 지정함
docker build - < docker.tar.gz
중간 이미지의 재이용
Docker는 이미지를 빌드할 때 자동으로 중간 이미지를 생성함
그리고 다른 이미지를 빌드할 때 중간 이미지를 내부적으로 재이용함으로써 빌드를 고속으로 수행함
이미지를 재이용하고 있을 때는 빌드 로그에 'Using cache' 라고 표시됨
이 캐시를 이용하고 싶지 않은 경우는 docker build
명령에서 --no-cache
옵션을 지정한다
Docker 이미지의 레이어 구조
4개의 명령을 갖고 있는 Dockerfile의 예
Dockerfile과 동일한 디렉토리에 임의의 'index.html' 이라는 이름의 파일을 생성하고 docker build
명령으로 이미지를 작성하면
각 레이어마다 이미지가 생성되어 네개의 이미지가 생성됨
# STEP:1 Ubuntu (베이스 이미지)
FROM ubuntu:latest
# STEP:2 Nginx 설치
RUN apt-get update && apt-get install -y -q nginx
# STEP:3 파일 복사
COPY index.html /usr/share/nginx/html/
# STEP:4 Nginx 시작
CMD ["nginx", "-g", "daemon off;"]
멀티스테이지 빌드를 사용한 Dockerfile 만들기
Sample 앱
git clone https://github.com/asashiho/dockertext2
cd dockertext2/chap05/multi-stage/
Dockerfile
- 개발 환경용 Docker 이미지
- 개발용 언어 Go 버전 1.8.4를 베이스 이미지로 작성
- builder 라는 별명을 붙임
- 개발에 필요한 버전을 설치하여 로컬 환경에 있는 소스코드를 컨테이너 안으로 복사함
- 소스코드를
go build
명령으로 빌드하여 greet 라는 이름의 실행 가능 바이너리 파일을 작성
- 제품 환경용 Docker 이미지
- 베이스 이미지는 busybox(기본적인 Linux 명령들을 하나의 파일로 모아 놓은 것, 최소한으로 필요한 Linux 쉘 환경 제공)를 사용
- 개발용 환경의 Docker 이미지로 빌드한 greet라는 이름의 실행 가능 바이너리 파일을 제품 환경용 Docker 이미지로 복사
--from
옵션을 사용하여 builder 라는 이름의 이미지로 부터 복사 한다는 것을 선언- 복사한 실행 가능 바이너리 파일을 실행하는 명령 작성
# 1. Build Image
FROM golang:1.8.4-jessie AS builder
# Install dependencies
WORKDIR /go/src/github.com/asashiho/greet
RUN go get -d -v github.com/urfave/cli
# build modules
COPY main.go .
RUN GOOS=linux go build -a -o greet .
# ------------------------------------------
# 2. Production Image
FROM busybox
WORKDIR /opt/greet/bin
# Deploy modules
COPY --from=builder /go/src/github.com/asashiho/greet/ .
ENTRYPOINT ["./greet"]
Docker 이미지의 빌드
docker build -t greet .
Sending build context to Docker daemon 3.584kB
Step 1/9 : FROM golang:1.13 AS builder
1.13: Pulling from library/golang
50e431f79093: Pull complete
dd8c6d374ea5: Pull complete
c85513200d84: Pull complete
55769680e827: Pull complete
15357f5e50c4: Pull complete
e2d9b328fba5: Pull complete
f8e0159fc852: Pull complete
Digest: sha256:e4ea85caf21a7030ac24ffc9b8324823f75a22364c46291af21323a7816f6493
Status: Downloaded newer image for golang:1.13
---> 3a7408f53f79
Step 2/9 : WORKDIR /go/src/github.com/asashiho/dockertext-greet
---> Running in 88d9b1a541b8
Removing intermediate container 88d9b1a541b8
---> a7b7daf7d308
Step 3/9 : RUN go get -d -v github.com/urfave/cli
---> Running in aee60f5633b2
github.com/urfave/cli (download)
github.com/cpuguy83/go-md2man (download)
Removing intermediate container aee60f5633b2
---> d8d813b0550d
Step 4/9 : COPY main.go .
---> b0a29f379b64
Step 5/9 : RUN GOOS=linux go build -a -o greet .
---> Running in afdf6b62fa3d
Removing intermediate container afdf6b62fa3d
---> 69201d429de8
Step 6/9 : FROM busybox
latest: Pulling from library/busybox
0669b0daf1fb: Pull complete
Digest: sha256:b26cd013274a657b86e706210ddd5cc1f82f50155791199d29b9e86e935ce135
Status: Downloaded newer image for busybox:latest
---> 83aa35aa1c79
Step 7/9 : WORKDIR /opt/greet/bin
---> Running in 953288dc5b27
Removing intermediate container 953288dc5b27
---> 287e50775818
Step 8/9 : COPY --from=builder /go/src/github.com/asashiho/dockertext-greet/ .
---> ae0e5536db5d
Step 9/9 : ENTRYPOINT ["./greet"]
---> Running in 9e9a22973ad5
Removing intermediate container 9e9a22973ad5
---> 56b7008ab820
Successfully built 56b7008ab820
Successfully tagged greet:latest
- Docker Hub에서 개발용 환경의 베이스 이미지인
goland:1.8.4-jessie
를 다운로드 - 개발 환경용 이미지 builder 생성
- builder 이미지로 소스코드를 빌드하여 실행 가능 바이너리 파일을 생성
- 제품 환경용 이미지에 실행 가능 바이너리 파일이 복사됨
이미지 확인
개발 환경용 이미지인 goland:1.8.4-jessie
는 803MB 지만 제품 환경용 greet 는 겨우 6.02MB
제품 환경용 베이스 이미지인 busybox 의 1.22MB에 애플리케이션의 실행에 필요한 모듈만을 추가한 정도임
제품 환경에서는 부하에 따라 작동하는 컨테이너의 수가 바뀜
가능한 한 용량이 적은 이미지를 사용하면 시스템 전체의 컴퓨팅 리소스를 효율적으로 활용할 수 있음
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
greet latest 56b7008ab820 41 seconds ago 6.02MB
busybox latest 83aa35aa1c79 6 days ago 1.22MB
golang 1.13 3a7408f53f79 2 weeks ago 803MB
Docker 컨테이너 실행
Sample 앱은 인수를 사용하여 인사를 반환하는 간단한 커맨드라인 툴이지만
제품 환경용으로 만든 저용량 이미지인 greet만으로 작동하고 있다는 것을 알 수 있음
docker container run -it --rm greet asa
Hello asa
docker container run -it --rm greet --lang=es asa
Hola asa