Docker 이미지 빌드 시 Layer 캐시 활용
Docker 이미지 빌드 성능을 향상시키기 위한 layer 캐시 전략을 알아봅니다.
Docker 이미지 빌드 시 Layer 캐시 활용
Docker 이미지 빌드 시간을 줄이려면 layer 캐시를 효과적으로 활용해야 합니다. 이 글에서는 layer 캐시 원리와 최적화 전략을 알아봅니다.
Environment
$ docker --version
Docker version 24.0.7, build afdd53b
$ docker buildx version
github.com/docker/buildx v0.12.1Problem: 빌드 시간이 매번 오래 걸림
# Bad Dockerfile - no cache optimization
FROM python:3.11
WORKDIR /app
# Every change invalidates cache for all layers below
COPY . .
RUN pip install -r requirements.txt
RUN python setup.py build# First build: 5 minutes
$ docker build -t myapp .
# After changing one line in app.py: Still 5 minutes!
$ docker build -t myapp .Analysis: Layer 캐시 동작 원리
# Docker builds layers sequentially
# Each layer is cached based on:
# 1. Base image (cached if same tag)
# 2. Instructions (RUN, COPY, etc.)
# 3. Content of files (COPY, ADD)
# Cache invalidation flow:
# COPY . . ← Changes invalidate this layer
# RUN pip install ← AND all subsequent layers
# RUN build ← This too# Check layer cache
$ docker history myapp
IMAGE CREATED CREATED BY SIZE
abc123def456 5 min ago CMD ["python" "app.py"] 0B
def456abc789 5 min ago RUN pip install -r requirements.txt 150MB
ghi789jkl012 5 min ago COPY . . 50KB
jkl012mno345 2 weeks ago WORKDIR /app 0B
mno345pqr678 2 weeks ago /bin/sh -c #(nop) FROM python:3.11 900MBSolution: Layer 캐시 최적화 전략
방법 1: 의존성 파일 먼저 복사
# Good Dockerfile - optimized for caching
FROM python:3.11-slim
WORKDIR /app
# 1. Copy only requirements first (changes rarely)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 2. Copy application code (changes frequently)
COPY . .
CMD ["python", "app.py"]# Build time comparison:
# Bad: 5 min (every time)
# Good: 30 sec (after first build, only COPY layer rebuilds)방법 2: Multi-stage Build
# Build stage
FROM python:3.11 as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Production stage
FROM python:3.11-slim
WORKDIR /app
# Copy only installed packages from builder
COPY --from=builder /root/.local /root/.local
# Copy application
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]방법 3: Dockerignore 활용
# .dockerignore
__pycache__
*.pyc
.git
.gitignore
.env
.venv
venv/
node_modules/
*.log
.coverage
htmlcov/
dist/
build/
*.egg-info/# Check what gets sent to daemon
$ docker build . 2>&1 | grep "Sending build context"
Sending build context to Docker daemon 15.2MB # Bad: includes .git
# After .dockerignore
Sending build context to Docker daemon 2.1MB # Good: only necessary files방법 4: 특정 파일만 복사
# Instead of COPY . .
# Copy specific files/directories
COPY ./src/ ./src/
COPY ./config/ ./config/
COPY requirements.txt .방법 5: BuildKit 캐시 활용
# syntax=docker/dockerfile:1
FROM python:3.11 as builder
WORKDIR /app
# Mount cache for pip
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]# Enable BuildKit
$ DOCKER_BUILDKIT=1 docker build -t myapp .
# Or in docker-compose.yml
# COMPOSE_DOCKER_CLI_BUILD=1 docker-compose buildAdvanced: 캐시 전략 비교
# No caching
$ docker build --no-cache -t myapp .
# Using local cache
$ docker build -t myapp .
# Using registry cache
$ docker build \
--cache-from type=registry,ref=registry.example.com/myapp:latest \
-t myapp .
# Using local directory cache
$ docker build \
--cache-from type=local,src=/tmp/docker-cache \
-t myapp .Lessons Learned
Layer 순서: 자주 변경되지 않는 레이어를 위에, 자주 변경되는 레이어를 아래에 배치하세요.
의존성 분리: requirements.txt 같은 의존성 파일은 소스 코드보다 먼저 복사하세요.
Multi-stage Build: 빌드 의존성과 런타임 의존성을 분리하면 이미지 크기를 줄일 수 있습니다.
BuildKit 활용: BuildKit은 캐시 관리와 병렬 빌드를 더 효율적으로 처리합니다.
.dockerignore 필수: 불필요한 파일이 빌드 컨텍스트에 포함되지 않도록 .dockerignore를 설정하세요.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.