Ответ
Мой процесс сборки Docker-образов нацелен на безопасность, минимальный размер и воспроизводимость. Вот ключевые практики:
1. Оптимизация Dockerfile:
- Многоступенчатая сборка (Multi-stage): Отделяю этап сборки (builder) от финального рантайм-образа, чтобы не тащить в продакшен компиляторы и исходный код.
- Минимизация слоев: Объединяю связанные
RUN,COPYкоманды и очищаю кэш пакетных менеджеров в одном слое. - Использование
.dockerignore: Обязательно исключаю ненужные файлы (.git,node_modules, лог-файлы), чтобы они не попали в контекст сборки.
2. Пример Dockerfile для Go-приложения:
# STAGE 1: Билд
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /myapp ./cmd/main.go
# STAGE 2: Рантайм
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /myapp .
# Копируем только бинарник, а не исходники
EXPOSE 8080
USER nobody
CMD ["./myapp"]
3. Безопасность:
- Использую минимальные базовые образы (
alpine,distroless). - Запускаю приложение от непривилегированного пользователя (
USER nobody). - Интегрирую сканирование уязвимостей (Trivy, Grype) в CI/CD пайплайн до пуша в реестр.
4. CI/CD интеграция:
Сборка происходит в пайплайне (например, GitLab CI). Использую кэширование слоев (--cache-from) для ускорения, тегирую образы по хешу коммита и семантическому версионированию, затем пушим в приватный реестр (Harbor, GitLab Container Registry).