DevOps

[Docker] Dockerfile 구성 및 빌드

nineDeveloper 2020. 3. 16. 21:49
728x90

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

  1. 개발 환경용 Docker 이미지
    • 개발용 언어 Go 버전 1.8.4를 베이스 이미지로 작성
    • builder 라는 별명을 붙임
    • 개발에 필요한 버전을 설치하여 로컬 환경에 있는 소스코드를 컨테이너 안으로 복사함
    • 소스코드를 go build 명령으로 빌드하여 greet 라는 이름의 실행 가능 바이너리 파일을 작성
  2. 제품 환경용 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
  1. Docker Hub에서 개발용 환경의 베이스 이미지인 goland:1.8.4-jessie를 다운로드
  2. 개발 환경용 이미지 builder 생성
  3. builder 이미지로 소스코드를 빌드하여 실행 가능 바이너리 파일을 생성
  4. 제품 환경용 이미지에 실행 가능 바이너리 파일이 복사됨

이미지 확인

개발 환경용 이미지인 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
728x90