https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
컨테이너는 멈추고 파기될 수 있고 언제든 바뀔수 있기에 최소한의 셋업과 설정으로 구성해야 하므로
도커 이미지를 정의하는 Dockerfile은 이를 염두해두고 생성해야한다.
`docker build` 명령을 실행하는 현재 디렉터리를 build context라고 하고 이 디렉터리안에 Dockerfile이 있습니다.
이 명령을 실행할 때 옵션으로 -f --file string(Default is 'PATH/Dockerfile')을 사용하면 다른 디렉터리에 있는 Dockerfile을 지정할 수 있다.
Dockerfile이 저장된 디렉터리의 위치는 상관이 없고,
그 디렉터리 안에 있는 모든 파일과 디렉터리들이 build context로서 도커 데몬에 보내지게 된다.
# Create a directory for the build context and cd into it.
# Write “hello” into a text file named hello and
# create a Dockerfile that runs cat on it.
# Build the image from within the build context (.):
mkdir myproject && cd myproject
echo "hello" > hello
echo -e "FROM busybox\nCOPY /hello /\nRUN cat /hello" > Dockerfile
docker build -t helloapp:v1 .
# Move Dockerfile and hello into separate directories
# and build a second version of the image
# (without relying on cache from the last build).
# Use -f to point to the Dockerfile and specify the directory of the build context:
mkdir -p dockerfiles context
mv Dockerfile dockerfiles && mv hello context
docker build --no-cache -t helloapp:v2 -f dockerfiles/Dockerfile context
이미지를 만드는데 필요없는 파일을 포함시키면 build context가 커지게되고
도커 데몬에 전달할 데이터가 커지게 된다.
이로 인해 이미지의 size가 커지게 되면서 build에 소요되는 시간, push와 pull에 소요되는 시간, run time등
모든작업의 실행에 소요되는 시간에 영향을 준다.
그렇기 때문에 Dockerfile을 build할 때 결과 메시지에서 이 크기를 가급적 줄이도록한다.
Sending build context to Docker daemon 187.8MB
.dockerignoer는 .gitignore와 유사하게 빌드에서 제외할 파일 패턴을 제외할 수 있도록 지원한다.
멀티 스테이지 빌드는 `FROM`이 1개가 아닌 2개 이상이 존재할 수 있고
이로 인해 빌드이미지와 실행이미지를 분리할 수 있어서 간편하게 이미지의 크기를 줄일 수 있다.
734.28MB -> 6.91MB로 감소
##############################################
FROM golang:1.19.3 AS builder
# Set Environment Variables
ENV HOME /app
ENV CGO_ENABLED 0
ENV GOOS linux
# go package install
WORKDIR /app
RUN go mod init mux
RUN go mod tidy
RUN go mod download
RUN go get github.com/gorilla/mux
COPY . .
RUN go build -a -o main .
##############################################
FROM scratch
WORKDIR /root/
# 이전stage에서 build했던 바이너리 파일을 복사
COPY --from=builder /app/main .
EXPOSE 8080
CMD [ "./main" ]
복잡도, 의존성, 파일크기, 빌드 시간등을 줄이기 위해서 불필요한 패키지들은 뺀다.
반드시 필요하지 않는 패키지를 의미하는데 예를 들면 Database 이미지에 텍스트 에디터 패키지는 필요가 없다.
각각의 컨테이너는 단일한 처리를 목적으로 한다.
어플리케이션을 디커플링해서 쪼개면 수평 확장과, 컨테이너 재사용이 쉬워진다.
예를 들어, 웹 어플리케이션을 스택을 3개의 컨테이너로 구성한다고 했을때
웹, 데이터 베이스, 인메모리 캐시로 분리하여 관리할 수 있다.
각 컨테이너를 디커플링하여 하나의 프로세스로 제한하는것은 경험상 좋은 규칙이지만 모두 그렇지는 않습니다.
Celery의 multiple worker process들과 Apache는 request마다 프로세스를 생서할 수도 있습니다.
(Spawned with an init process)
컨테이너를 가능하면 모듈화하고 명확하게 관리하면서 최선의 선택을 한다.
컨테이너간에 서로 의존적이라면 Docker container networks로 서로간 통신하게 할 수도 있다.
가능하다면, 여러 줄의 인수를 알파벳순으로 정렬하는 것이 좋다. 이렇게 하면 패키지 중복을 방지하고 쉽게 업데이트 할 수 있다. 또한 PR을 읽고 검토하기에 용이해진다. '\' 앞에 공백을 추가하는 것도 도움이 된다.
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion \
&& rm -rf /var/lib/apt/lists/*
이미지를 빌드할때, 도커는 Dockerfile에 설정한 순서대로 실행한다.
각 명령을 검토할 때 도커는 새로운 (중복) 이미지를 만들지 않고 캐시에서 재사용할 수 있는 이미지를 찾는다.
캐시를 사용하지 않으려면 docker build 할때 --no-cache=true 옵션을 사용할 수 있다.
도커가 캐시를 활용할 수 있도록 하기 위해서는, 일치하는 이미지를 찾을 수 있는 경우와 없는 경우에 대해 이해하는 것이 중요하다.
도커가 따르는 기본적인 규칙은 아래와 같다.
일단 캐시가 무효화되면 이후의 모든 Dockerfile 명령은 새로운 이미지를 생성하며, 캐시는 사용되지 않는다.
docker build를 수행할 때 pipe를 이용하여 Dockerfile을 disk에 만들지 않을 수도 있다.
일회성 빌드나 테스트 같이 가볍게 사용할때 유용하다.
# For example, the following commands are equivalent:
echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -
docker build -<<EOF
FROM busybox
RUN echo "hello world"
EOF
# You can substitute the examples with your preferred approach,
# or the approach that best fits your use-case.
docker build 할때 `-` 하이픈 옵션을 사용하면 Dockerfile을 생성하지 않고 build context 전송하지도 않아서
build 속도를 향상 시킬 수 있다.
docker build -t myimage:latest -<<EOF
FROM busybox
RUN echo "hello world"
EOF
주의할점은 COPY 혹은 ADD를 사용하는 경우라면 실패
# create a directory to work in
mkdir example
cd example
# create an example file
touch somefile.txt
docker build -t myimage:latest -<<EOF
FROM busybox
COPY somefile.txt ./
RUN cat /somefile.txt
EOF
# observe that the build fails
...
Step 2/3 : COPY somefile.txt ./
COPY failed: stat /var/lib/docker/tmp/docker-builder249218248/somefile.txt: no such file or directory
인프라 개념 LACP (1493) | 2022.06.10 |
---|---|
Python으로 Opendistro Account 생성하기 (615) | 2021.03.17 |
Cloudfront와 S3를 이용한 웹 서비스 구성 (1938) | 2021.03.10 |
Hashicorp Terraform (테라폼) (757) | 2020.10.28 |
AWS Subnet 생성하기 (2534) | 2020.07.23 |