Multi-stage builds, кэширование слоёв, уменьшение размера образов.
Оптимизация Docker-образов критична для скорости CI-пайплайнов и эффективности production-развёртываний. Изучите техники уменьшения размера образов и ускорения сборок.
Оптимизация даёт:
┌─────────────────────────────────────────────────────────────┐
│ Оптимизация │
│ │
│ До: 1.2GB → Сборка 15min → Деплой 5min │
│ После: 150MB → Сборка 3min → Деплой 30sec │
└─────────────────────────────────────────────────────────────┘
# Этап 1: Сборка
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Этап 2: Production
FROM node:18-alpine
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY package*.json ./
CMD ["node", "dist/index.js"]Результат:
# Этап сборки зависимостей
FROM python:3.11 AS builder
WORKDIR /app
# Устанавливаем компиляторы
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
# Финальный образ
FROM python:3.11-slim
WORKDIR /app
# Копируем только wheel-пакеты
COPY /wheels /wheels
RUN pip install --no-cache-dir /wheels/*
# Копируем приложение
COPY . .
CMD ["python", "app.py"]# Build stage
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 -a -installsuffix cgo -o main .
# Final stage
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY /app/main .
CMD ["./main"]Результат:
# Плохо — кэш сбрасывается при каждом изменении кода
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt# Хорошо — зависимости кэшируются
FROM python:3.11-slim
WORKDIR /app
# Копируем только файл зависимостей
COPY requirements.txt .
# Кэшируемый слой с установкой
RUN pip install --no-cache-dir -r requirements.txt
# Копируем код (часто меняется, кэш не важен)
COPY . .# Плохо — много слоёв
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN rm -rf /var/lib/apt/lists/*
# Хорошо — один слой
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
wget && \
rm -rf /var/lib/apt/lists/*Важно: Очистка (rm -rf) должна быть в той же RUN-инструкции, иначе слой с удалёнными файлами всё равно займёт место.
# Python образы
python:3.11 # ~900MB
python:3.11-slim # ~150MB
python:3.11-alpine # ~50MB
# Node.js образы
node:18 # ~1GB
node:18-slim # ~200MB
node:18-alpine # ~170MB
# Go образы
golang:1.21 # ~800MB
golang:1.21-alpine # ~300MBПреимущества:
Недостатки:
# Alpine с необходимыми зависимостями
FROM python:3.11-alpine
RUN apk add --no-cache \
gcc \
musl-dev \
libffi-dev \
openssl-dev
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]Slim-образы — хороший баланс размера и совместимости:
FROM python:3.11-slim
# Устанавливаем только необходимое
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]# .dockerignore
.git
.gitignore
__pycache__
*.pyc
*.pyo
*.pyd
.pytest_cache
.coverage
htmlcov/
.env
.venv
venv/
*.egg-info/
.mypy_cache/
.ruff_cache/
.vscode/
.idea/
*.md
*.rst
Dockerfile*
docker-compose*
.dockerignore
# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
.env
.env.*
*.md
.vscode/
.idea/
coverage/
.nyc_output/
dist
build
*.log
.DS_Store
Thumbs.db
Эффект: Уменьшение контекста с 500MB до 5MB ускоряет передачу Docker Daemon в 100 раз.
# Через переменную окружения
export DOCKER_BUILDKIT=1
docker build -t myapp .
# Через синтаксис в Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.11-slim# syntax=docker/dockerfile:1
FROM python:3.11-slim
# Монтируем секрет только во время сборки
RUN \
pip install --index-url https://__token__:${(cat /run/secrets/pypi-token)}@pypi.org/simple/ private-package# GitHub Actions
- name: Build with secrets
uses: docker/build-push-action@v5
with:
secrets: |
pypi-token=${{ secrets.PYPI_TOKEN }}name: Build with Cache
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=maxТипы кэша:
type=gha — GitHub Actions Cachetype=registry — кэш в Docker-реестреtype=local — локальный кэш на runner# syntax=docker/dockerfile:1
FROM python:3.11-slim
# Кэшируем pip cache между сборками
RUN \
pip install requests flask django
# Кэшируем node_modules
FROM node:18-alpine
RUN \
npm ci# syntax=docker/dockerfile:1
FROM python:3.11-slim AS builder
WORKDIR /app
# Устанавливаем зависимости для компиляции
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
# Кэшируем pip
RUN \
pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
# Финальный образ
FROM python:3.11-slim
WORKDIR /app
# Копируем wheel-пакеты
COPY /wheels /wheels
RUN pip install --no-cache-dir /wheels/*
# Копируем приложение
COPY . .
# Создаём не-root пользователя
RUN useradd -m -u 1000 appuser
USER appuser
CMD ["python", "app.py"]# syntax=docker/dockerfile:1
FROM node:18-alpine AS builder
WORKDIR /app
# Кэшируем npm
COPY package*.json ./
RUN \
npm ci
COPY . .
RUN npm run build
# Production образ
FROM node:18-alpine
WORKDIR /app
# Копируем только необходимое
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY /app/package*.json ./
# Не-root пользователь
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
CMD ["node", "dist/index.js"]# syntax=docker/dockerfile:1
# Build stage
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN \
mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# Run stage
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]# Анализ образа
docker scout cves myapp:latest
# Рекомендации по оптимизации
docker scout recommendations myapp:latest# Просмотр слоёв
docker history myapp:latest
# С размером каждого слоя
docker history --no-trunc myapp:latest# Установка
docker pull wagoodman/dive
# Анализ образа
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive myapp:latestDive показывает:
# Всегда исключайте
.git
node_modules
__pycache__
*.log
.env
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .RUN apt-get update && \
apt-get install -y pkg1 pkg2 && \
rm -rf /var/lib/apt/lists/*FROM golang:1.21 AS builder
# ... build ...
FROM alpine:3.18
COPY /app/main .RUN useradd -m -u 1000 appuser
USER appuser# Плохо
FROM python:latest
# Хорошо
FROM python:3.11.7-slimRUN apt-get update && \
apt-get install -y pkg && \
rm -rf /var/lib/apt/lists/*Ключевые техники оптимизации:
В следующей теме вы изучите мультиплатформенную сборку образов для разных архитектур.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.