Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Оптимизация Docker-сборок
docker_optimization

Оптимизация Docker-сборок

Multi-stage builds, кэширование слоёв, уменьшение размера образов.

Оптимизация Docker-сборок

Оптимизация Docker-образов критична для скорости CI-пайплайнов и эффективности production-развёртываний. Изучите техники уменьшения размера образов и ускорения сборок.

#Зачем оптимизировать Docker-образы?

Оптимизация даёт:

  • Быстрые CI-сборки — меньше времени на билд и пуш
  • Быстрый деплой — образы быстрее скачиваются в production
  • Экономия ресурсов — меньше места на диске и в реестре
  • Безопасность — меньшая поверхность атаки
┌─────────────────────────────────────────────────────────────┐
│                    Оптимизация                              │
│                                                              │
│  До: 1.2GB  →  Сборка 15min  →  Деплой 5min               │
│  После: 150MB →  Сборка 3min   →  Деплой 30sec            │
└─────────────────────────────────────────────────────────────┘

#Multi-Stage Builds

#Базовый пример

# Этап 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 --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ CMD ["node", "dist/index.js"]

Результат:

  • Без multi-stage: ~1GB
  • С multi-stage: ~200MB

#Python multi-stage build

# Этап сборки зависимостей 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 --from=builder /wheels /wheels RUN pip install --no-cache-dir /wheels/* # Копируем приложение COPY . . CMD ["python", "app.py"]

#Go multi-stage build

# 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 --from=builder /app/main . CMD ["./main"]

Результат:

  • Full golang image: ~800MB
  • Alpine с бинарником: ~15MB

#Оптимизация слоёв

#Порядок инструкций важен

# Плохо — кэш сбрасывается при каждом изменении кода 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-инструкций

# Плохо — много слоёв 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

Преимущества:

  • Минимальный размер (~5MB базовый образ)
  • Меньше уязвимостей
  • Быстрая загрузка

Недостатки:

  • Может потребоваться установка дополнительных библиотек
  • Проблемы с совместимостью (musl libc vs glibc)
  • Некоторые Python-пакеты требуют компиляции
# 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

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

#Пример для Python-проекта

# .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

#Пример для Node.js-проекта

# .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 раз.

#Docker BuildKit

#Включение BuildKit

# Через переменную окружения export DOCKER_BUILDKIT=1 docker build -t myapp . # Через синтаксис в Dockerfile # syntax=docker/dockerfile:1 FROM python:3.11-slim

#Преимущества BuildKit

  1. Параллельное выполнение независимых инструкций
  2. Улучшенное кэширование с возможностью экспорта
  3. Секреты во время сборки без попадания в образ
  4. Mount cache для ускорения установки зависимостей

#Использование секретов в BuildKit

# syntax=docker/dockerfile:1 FROM python:3.11-slim # Монтируем секрет только во время сборки RUN --mount=type=secret,id=pypi-token \ 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 }}

#Кэширование с BuildKit в CI

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 Cache
  • type=registry — кэш в Docker-реестре
  • type=local — локальный кэш на runner

#Mount cache для зависимостей

# syntax=docker/dockerfile:1 FROM python:3.11-slim # Кэшируем pip cache между сборками RUN --mount=type=cache,target=/root/.cache/pip \ pip install requests flask django # Кэшируем node_modules FROM node:18-alpine RUN --mount=type=cache,target=/root/.npm \ npm ci

#Оптимизация для конкретных языков

#Python

# 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 --mount=type=cache,target=/root/.cache/pip \ pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt # Финальный образ FROM python:3.11-slim WORKDIR /app # Копируем wheel-пакеты COPY --from=builder /wheels /wheels RUN pip install --no-cache-dir /wheels/* # Копируем приложение COPY . . # Создаём не-root пользователя RUN useradd -m -u 1000 appuser USER appuser CMD ["python", "app.py"]

#Node.js

# syntax=docker/dockerfile:1 FROM node:18-alpine AS builder WORKDIR /app # Кэшируем npm COPY package*.json ./ RUN --mount=type=cache,target=/root/.npm \ npm ci COPY . . RUN npm run build # Production образ FROM node:18-alpine WORKDIR /app # Копируем только необходимое COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package*.json ./ # Не-root пользователь RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 USER nodejs CMD ["node", "dist/index.js"]

#Java (Spring Boot)

# syntax=docker/dockerfile:1 # Build stage FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /app COPY pom.xml . RUN --mount=type=cache,target=/root/.m2 \ mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # Run stage FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --from=builder /app/target/*.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]

#Анализ размера образа

#Docker Scout

# Анализ образа docker scout cves myapp:latest # Рекомендации по оптимизации docker scout recommendations myapp:latest

#Docker history

# Просмотр слоёв docker history myapp:latest # С размером каждого слоя docker history --no-trunc myapp:latest

#Dive

# Установка docker pull wagoodman/dive # Анализ образа docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ wagoodman/dive myapp:latest

Dive показывает:

  • Размер каждого слоя
  • Какие файлы добавлены/изменены
  • Неиспользуемые файлы (wasted space)

#Best Practices

#1. Используйте .dockerignore

# Всегда исключайте
.git
node_modules
__pycache__
*.log
.env

#2. Копируйте зависимости перед кодом

COPY requirements.txt . RUN pip install -r requirements.txt COPY . .

#3. Объединяйте RUN-инструкции

RUN apt-get update && \ apt-get install -y pkg1 pkg2 && \ rm -rf /var/lib/apt/lists/*

#4. Используйте multi-stage

FROM golang:1.21 AS builder # ... build ... FROM alpine:3.18 COPY --from=builder /app/main .

#5. Не используйте root в production

RUN useradd -m -u 1000 appuser USER appuser

#6. Используйте конкретные теги

# Плохо FROM python:latest # Хорошо FROM python:3.11.7-slim

#7. Очищайте кэш в том же слое

RUN apt-get update && \ apt-get install -y pkg && \ rm -rf /var/lib/apt/lists/*

Далее: Мультиплатформенная сборка