Ответ
Основное отличие — использование многоэтапной сборки (multi-stage build) для компилируемых языков. Это позволяет создать минимальный итоговый образ, содержащий только скомпилированный бинарный файл, без компиляторов, исходного кода и промежуточных артефактов.
Dockerfile для компилируемого языка (Go):
# Первый этап (builder): среда для компиляции
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/app
# Второй этап (финальный): минимальный образ для запуска
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# Копируем ТОЛЬКО бинарник из этапа builder
COPY --from=builder /myapp .
CMD ["./myapp"]
Dockerfile для интерпретируемого языка (Python):
# Обычно одноэтапная сборка
FROM python:3.11-slim
WORKDIR /app
# Копируем зависимости и устанавливаем их
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Копируем весь исходный код
COPY . .
CMD ["python", "main.py"]
Ключевые различия:
- Размер образа: Итоговый образ для Go (на основе
alpine) может весить ~10-20 МБ. Образ для Python, даже наslim, с установленными пакетами легко достигает 100+ МБ. - Безопасность: В финальном образе для компилируемого языка нет компилятора и исходного кода, что уменьшает поверхность для атаки.
- Содержимое: В Python-образе остаются все исходные файлы
.py, что необходимо для работы интерпретатора.