개요
- 도커 이미지 크기를 줄일 수 있는 방법에 대해 찾아본다.
- skaffold dev 명령어로 이미지 초기 생성시 필요한 패키지를 설치하는 과정이 빌드 과정의 많은 시간을 차지하는 문제가 있어 이를 줄일 수 있는 방법에 대해 찾아본다.
기술 스택
- Docker Multi stage build
- Docker Buildkit in Skaffold
- Python Wheel
구현 방법
Multi stage build 및 buildKit 사용
도커 이미지를 빌드 할 때 소스 코드만 변경해도 필요한 패키지들을 모두 설치하는 과정이 포함되어 빌드 시간이 길게는 15초까지 소모됐다. 이를 해결하기 위해 Docker에서 지원하는 Multi stage build 및 buildKit을 사용한다.
Multi stage build란 하나의 Dockerfile에 여러 이미지를 정의하고, 이미지끼리 결과물을 복사할 수 있는 기능이다.
BuildKit은 변경 내용과 관련 없는 stage를 캐시 처리 해주고 stage간 빌드 병렬 처리를 지원하는 기능이다.
(BuildKit VS Legacy builder)
Docker 공식 문서
이를 사용하면 중간 이미지들은 최종 이미지에 포함되지 않으므로 용량을 줄일 수 있다. 또 중간 이미지를 캐시 처리 할 수 있기 때문에 빌드 시간도 줄일 수 있다.
예를 들어 개발환경, 배포환경 각각 이미지를 하나씩 만들고, 개발환경에서는 컴파일러 등 빌드에 필요한 패키지들을 설치하고 이미지를 빌드한다. 배포용 이미지에서는 깨끗한 OS 이미지에 개발환경 이미지로부터 빌드된 바이너리 파일만 복사해오는 형태로 용량을 줄일 수 있다.
아래 예시에서는 필요한 패키지들을 base 이미지에서 wheel 확장자로 설치하고, runtime 이미지에서는 wheel 패키지들을 복사해서 설치한 후 소스 코드를 복사한 뒤 실행시킨다.
ARG WHEEL_DIST="/tmp/wheels"
# Install requirements as wheel
FROM python:3.9-slim-buster AS base
ARG WHEEL_DIST
ENV PYTHONUNBUFFERED 1
# Install python pakcages
COPY ./backend/requirements.txt .
RUN apt-get update \
&& pip install --upgrade pip \
&& apt-get install -y libpq-dev gcc \
&& python3 -m pip wheel -w "${WHEEL_DIST}" -r requirements.txt \
&& rm -rf /var/lib/apt/lists/*
# Application runtime using installed wheel
FROM python:3.9-slim-buster AS runtime
ENV PYTHONUNBUFFERED 1
ARG WHEEL_DIST
# Load installed wheel
WORKDIR "${WHEEL_DIST}"
COPY --from=base "${WHEEL_DIST}" .
RUN apt-get update \
&& apt-get install -y libpq-dev \
&& pip install --upgrade pip \
&& pip install --no-cache ./*
# Copy backend source
WORKDIR /backend
RUN mkdir -p /var/log/containers \
&& mkdir -p /backend
COPY ./backend /backend/
# Start this container with environment argument
...
적용 후 소스 코드를 변경하고 재빌드 하면 결과 화면처럼 패키지 설치 layer들은 캐시 처리 되고, 소스 변경과 관련된 layer만 실행되는 것을 볼 수 있다.
Python wheels: Python Wheels
Base image 경량화 및 캐시 처리
도커 이미지 크기 중 대부분은 base image인 python 3.9와 패키지를 설치하는 빌드 과정이 차지를 하고 있다.
먼저 python 3.9 대신3.9-slim-buster 버전을 사용하여 이미지 크기를 낮춘다.
또한 이미지를 빌드 할 때 base image를 캐시 처리하여 python 이미지를 불러오는 시간을 줄인다.
docker에서는 빌드 시 --cache-from
옵션을 사용하고, skaffold 에서는 build.artifacts.docker.cacheFrom
옵션을 사용한다.
apiVersion: skaffold/v2beta15
kind: Config
build:
artifacts:
- context: src
image: backend
docker:
dockerfile: ./backend/Dockerfile.k8s
target: runtime
# target: runtime
cacheFrom:
- python:3.9-slim-buster
...
결과
소스 코드만 변경하여 빌드 할 경우 아래 로그에서 볼 수 있듯 소스 코드와 관련된 부분만 처리를 하고 패키지 설치 등과 같은 작업들은 캐시 처리된다.
'CICD' 카테고리의 다른 글
[Skaffold] JIB Sync (0) | 2024.01.04 |
---|