devops2024-01-20·7 min·328/348

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.1

Problem: 빌드 시간이 매번 오래 걸림

# 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             900MB

Solution: 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 build

Advanced: 캐시 전략 비교

# 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

  1. Layer 순서: 자주 변경되지 않는 레이어를 위에, 자주 변경되는 레이어를 아래에 배치하세요.

  2. 의존성 분리: requirements.txt 같은 의존성 파일은 소스 코드보다 먼저 복사하세요.

  3. Multi-stage Build: 빌드 의존성과 런타임 의존성을 분리하면 이미지 크기를 줄일 수 있습니다.

  4. BuildKit 활용: BuildKit은 캐시 관리와 병렬 빌드를 더 효율적으로 처리합니다.

  5. .dockerignore 필수: 불필요한 파일이 빌드 컨텍스트에 포함되지 않도록 .dockerignore를 설정하세요.


This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.