Сколько может быть инструкций FROM в Dockerfile?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Сколько инструкций FROM может быть в Dockerfile?
В классическом, одиночном процессе сборки (docker build), Dockerfile может содержать несколько инструкций FROM, но с критически важным ограничением: каждая инструкция FROM начинает новую стадию сборки (stage), и в итоговый образ попадает содержимое только последней стадии. Это фундаментальная концепция многостадийных сборок (multi-stage builds), появившаяся в Docker 17.05.
Таким образом, технически количество инструкций FROM не ограничено (пока хватает ресурсов), но каждая из них создает независимый контекст сборки.
Ключевые принципы и использование
- Цель многостадийных сборок: Резкое уменьшение размера итогового образа за счет разделения сборки (build stage) и финального рантайма (runtime stage).
* На ранних стадиях используются тяжелые образы с компиляторами, SDK, вспомогательными инструментами.
* На финальной стадии используется минимальный образ (часто `alpine` или `scratch`), куда копируются **только** скомпилированные артефакты из предыдущих стадий.
-
Именование стадий: Стадиям можно (и нужно) давать имена с помощью ключевого слова
AS. Это позволяет явно ссылаться на них позже.FROM golang:1.21-alpine AS builder WORKDIR /app COPY . . RUN go build -o myapp . FROM alpine:latest AS final COPY --from=builder /app/myapp /usr/local/bin/myapp CMD ["myapp"] -
Копирование между стадиями: Инструкция
COPY --from=<stage_name>позволяет копировать файлы из любой предыдущей стадии или даже из внешнего образа (например,COPY --from=nginx:latest /etc/nginx/nginx.conf /config/).
Пример многостадийного Dockerfile для приложения на Go
# Стадия 1: Сборка приложения
FROM golang:1.21-alpine AS builder
RUN apk add --no-cache git ca-certificates
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o /bin/myapp ./cmd/app
# Стадия 2: Сборка фронтенда (параллельная концептуальная стадия)
FROM node:18-alpine AS frontend-builder
WORKDIR /app
COPY frontend/ .
RUN npm ci && npm run build
# Стадия 3: Создание минимального финального образа
FROM alpine:latest AS final
RUN apk add --no-cache tzdata && cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime
WORKDIR /root/
# Копируем бинарник Go из стадии 'builder'
COPY --from=builder /bin/myapp .
# Копируем статику фронтенда из стадии 'frontend-builder'
COPY --from=frontend-builder /app/dist ./static
# Запускаем приложение
EXPOSE 8080
CMD ["./myapp"]
В этом примере три инструкции FROM, создающие три независимые стадии. В финальный образ final попадает только содержимое Alpine Linux и два скопированных артефакта, без всего инструментария Go и Node.js, что экономит сотни мегабайт.
Важные нюансы
- Аргументы и переменные среды: Объявленные с помощью
ARGилиENVв одной стадии не доступны в другой, если их явно не переобъявить. Каждая стадия — изолированный контекст. - История и кэш: Docker кэширует слои для каждой стадии отдельно. Изменения в одной стадии не инвалидируют кэш для другой.
- Сборка конкретной стадии: Можно собрать только промежуточную стадию для отладки или извлечения артефактов с помощью флага
--target.docker build --target builder -t myapp:builder . - Одиночная стадия: Если вам не нужна многостадийность, используйте только одну инструкцию
FROMв начале файла.
Вывод
Инструкций FROM в Dockerfile может быть столько, сколько необходимо стадий сборки. Их множественное использование — это не ошибка, а мощный стандартный подход (best practice) для создания оптимизированных, безопасных и минималистичных образов контейнеров путем разделения обязанностей между стадиями сборки и выполнения. Главное — четко понимать, что каждая инструкция FROM начинает новый, изолированный контекст, и управлять переносом артефактов между ними с помощью COPY --from.