지금까지 터미널에서 Docker를 다루는 명령어에 대해서 정리를 하고 공부를 했다. 이제는 Docker Image를 생성하는데 많이 사용되는 Dockerfile에 대해서 공부를 할 예정이다. 사실 글을 적기 전에 Docker로 Django나 Spring Framework를 연동할 때 Dockerfile로 올린 적이 있었다. 그 때는 Dockerfile의 구성 요소가 어떤 요소인지 모르고 다른 글이나 Docs를 따라 작성했었기 때문에 알지 못하는 점이 많았다.
기본적으로 Dockerfile은 이미지를 생성하는데 필요한 모든 명령어 모음집이라고 할 수 있다.
예를 들면, Dockerfile은 아래와 같이 기본적인 text file로 구성이 되어 있다.
FROM ubuntu:180.04
COPY . /app
RUN make /app
CMD python /app/app.py
각 명령어에 대해서 설명해보자면 주로 4가지로 구성되어 있다.
이 파일은 우분투 내에서 파이썬 파일을 실행하고자 하는 Dockerfile로 볼 수 있다.
# syntax=docker/dockerfile:1
FROM golang:1.16-alpine AS build
# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only
# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]
Dockerfile에 불필요한 패키지들을 설치하지 말고 프론트/백/DB 등 여러 구성 요소들을 한번에 묶어서 적어놓아 설치하지 않게 해야 한다.
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion \
&& rm -rf /var/lib/apt/lists/*
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="ACME Incorporated"
LABEL vendor2=ZENITH\ Incorporated
LABEL com.example.release-date="2015-02-12"
LABEL com.example.version.is-production=""
만약 하나의 이미지에 여러 라벨을 붙인다면!?
LABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"
or 백슬래시를 넣을 수 있음
LABEL vendor=ACME\ Incorporated \
com.example.is-beta= \
com.example.is-production="" \
com.example.version="0.0.1-beta" \
com.example.release-date="2015-02-12"
예시) shell과 exec 각각의 형태
1. shell
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
2. exec
RUN ["/bin/bash", "-c", "echo hello"]
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo \
&& rm -rf /var/lib/apt/lists/*
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl nginx
1. shell 형태
FROM ubuntu
CMD echo "This is a test." | wc -
2. exec 형태
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
EXPOSE <port> [<port>/<protocol>...]
EXPOSE 80/udp
TCP와 UDP 둘다 expose 할 경우
EXPOSE 80/tcp
EXPOSE 80/udp
docker run -p 80:80/tcp -p 80:80/udp ...
ENV <key>=<value> ...
예시) 3줄로 작성하기
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
예시) 한 줄로 작성하기
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy
예시) 환경 경로 참고하기
FROM alpine
ENV ADMIN_USER="mark"
RUN echo $ADMIN_USER > ./mark
RUN unset ADMIN_USER
$ docker run --rm test sh -c 'echo $ADMIN_USER'
만약 환경 변수가 많이 존재하지 않는다면, 명령어 안에 환경 경로를 설정하는 것이 낫다
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
예시 1) COPY
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
예시 2) ADD
ADD https://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
지금까지 Dockerfile을 작성하는 팁 및 여러가지 구성 요소에 대해서 정리를 해봤다. Dockerfile 구성 요소에 ENRTYPOINT나 VOLUME, USER, WORKDIR, ONBUILD 도 있지만 자주 사용하는 요소들에 대해서 적어봤다. 추가적으로 더 정보가 필요하다면 아래의 Docker Docs에서 찾아볼 수 있다.
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/