Ответ
Оптимизация слоев Docker-образов — это ключевая практика для уменьшения размера образов, ускорения сборки и развертывания. Я использую несколько основных подходов:
1. Многоступенчатая сборка (Multi-stage build) Позволяет использовать промежуточные образы для сборки, а в финальный образ копировать только необходимые артефакты.
# Этап сборки
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /myapp
# Финальный образ
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /myapp .
CMD ["./myapp"]
2. Объединение RUN-команд и очистка в одном слое Каждая инструкция в Dockerfile создает новый слой. Объединение команд уменьшает количество слоев и позволяет удалять временные файлы в том же слое, где они создавались.
# Плохо: создает несколько слоев
RUN apt-get update
RUN apt-get install -y package
RUN rm -rf /var/lib/apt/lists/*
# Хорошо: один слой с очисткой
RUN apt-get update &&
apt-get install -y package &&
rm -rf /var/lib/apt/lists/*
3. Использование минимальных базовых образов
- Alpine Linux — ультралегкий дистрибутив (~5 МБ)
- Distroless от Google — содержат только приложение и его зависимости
- Scratch — пустой образ для статически скомпилированных приложений
4. Правильное копирование файлов
- Использование
.dockerignoreдля исключения ненужных файлов (логов, временных файлов,.git) - Копирование зависимостей отдельно от исходного кода для лучшего кэширования слоев
5. Порядок инструкций Располагаю реже изменяемые инструкции (установка зависимостей) выше, а часто изменяемые (копирование исходного кода) — ниже, чтобы максимально использовать кэш Docker.