Перейти к содержимому

11. Multi-stage сборки

Multi-stage builds (многоэтапные сборки) — одна из мощнейших возможностей Docker. Они позволяют создавать минимальные production-образы, используя несколько FROM инструкций в одном Dockerfile. Инструменты сборки остаются только на промежуточных этапах, не попадая в финальный образ.

Без multi-stage builds у вас два варианта: огромный образ со всеми инструментами сборки, или несколько Dockerfile с ручным управлением артефактами.

# ❌ Один этап — всё в одном образе
FROM node:20 # 1.1 GB!
WORKDIR /app
COPY package*.json ./
RUN npm install # devDependencies тоже!
COPY . .
RUN npm run build
# Финальный образ: ~1.5 GB
# Содержит: npm, node_modules с devDep, исходный код, тесты
# ✅ Multi-stage — минимальный финальный образ
# Этап 1: Builder
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci # включая devDependencies
COPY . .
RUN npm run build # компиляция TypeScript, webpack
# Этап 2: Production
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production # только production deps
COPY --from=builder /app/dist ./dist # только результат сборки!
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/server.js"]
# Финальный образ: ~200 MB
FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./
FROM base AS deps
RUN npm ci
FROM base AS dev-deps
RUN npm ci # включая devDependencies
FROM dev-deps AS builder
COPY . .
RUN npm run build
FROM dev-deps AS tester
COPY . .
RUN npm test
FROM base AS production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/server.js"]
# Копировать из именованного этапа
COPY --from=builder /app/dist ./dist
# Копировать из конкретного образа
COPY --from=nginx:alpine /etc/nginx/nginx.conf /etc/nginx/nginx.conf
# Копировать по номеру этапа (0-based)
COPY --from=0 /app/dist ./dist
# Этап 1: Сборка React
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# /app/build содержит статические файлы
# Этап 2: Nginx для раздачи статики
FROM nginx:alpine AS production
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# Финальный образ: ~25 MB вместо ~1.5 GB!
# Этап 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 server ./cmd/server
# Этап 2: Минимальный образ
FROM scratch AS production
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
# Финальный образ: только бинарник! ~8 MB
Окно терминала
# Собрать до конкретного этапа (полезно для дебага)
docker build --target builder -t myapp:debug .
docker build --target production -t myapp:prod .
# Запустить тесты на builder этапе
docker build --target tester -t myapp:test .
docker run myapp:test