Ответ
При создании Docker-образов я придерживаюсь нескольких ключевых требований для обеспечения безопасности, эффективности и воспроизводимости:
-
Использование минимальных базовых образов: Я предпочитаю
alpineдля большинства случаев илиscratchдля самодостаточных бинарных файлов. Это радикально уменьшает размер образа и поверхность для атак.FROM alpine:3.18 -
Многоступенчатые сборки (Multi-stage builds): Это основной инструмент для минимизации финального образа. Я компилирую код в одном образе с полным SDK, а затем копирую только готовый артефакт в чистый финальный образ.
# Этап сборки FROM golang:1.21-alpine AS builder WORKDIR /app COPY . . RUN go build -o myapp . # Финальный этап FROM alpine:3.18 COPY --from=builder /app/myapp /usr/local/bin/ CMD ["myapp"] -
Минимизация слоев и очистка кэша: Я объединяю связанные команды
RUNи всегда удаляю кэш менеджера пакетов в одном слое, чтобы не увеличивать размер.RUN apk add --no-cache nginx && rm -rf /tmp/* /var/cache/apk/* -
Запуск от непривилегированного пользователя: Я никогда не оставляю контейнеры запущенными от
root. Создаю отдельного пользователя и группу.RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -D appuser USER appuser -
Использование
.dockerignore: Файл.dockerignoreобязателен, чтобы исключить из контекста сборки ненужные файлы (.git,node_modules, лог-файлы), что ускоряет сборку и предотвращает утечку чувствительных данных. -
Явное указание тегов версий: Я избегаю тегов
latestвFROMи для устанавливаемых пакетов, чтобы обеспечить детерминированную сборку.
Следование этим правилам позволяет создавать образы размером в десятки мегабайт вместо гигабайт, что ускоряет их скачивание, развертывание и повышает безопасность.