Ответ
Не рекомендуется объединять установку и сборку в один слой RUN. Это противоречит лучшим практикам Docker, так как приводит к увеличению размера образа из-за кэширования промежуточных артефактов и оставшихся файлов зависимостей (например, node_modules).
Правильный подход — использование многоступенчатой сборки (multi-stage build):
- Этап сборки (builder): Установите зависимости и соберите приложение.
- Финальный этап: Скопируйте только необходимые артефакты (бинарники, статику) в чистый, минимальный образ.
Пример для Go-приложения:
# Этап 1: Сборка
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 ./cmd/app
# Этап 2: Финальный образ
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /myapp .
CMD ["./myapp"]
Ключевые преимущества:
- Минимальный размер финального образа: В нем нет компилятора, исходного кода и временных файлов.
- Улучшенная безопасность: Уменьшается поверхность для атак (меньше пакетов и утилит).
- Эффективное кэширование слоев: Изменения в исходном коде не инвалидируют кэш слоя с зависимостями (
go mod download).