Docker Engine 29: как изменения в хранении образов повлияют на ваши проекты
Анализируем важные изменения в Docker Engine 29, связанные с переходом на containerd как хранилище образов по умолчанию. Узнайте о проблеме дублирования слоев и способах решения.
Docker Engine 29 перешел на containerd: почему ваши базовые слои теперь дублируются и как это исправить
⚡️ Новая эра контейнеризации: неожиданные последствия обновления
Вы установили Docker Engine 29 и столкнулись с пугающим увеличением использования дискового пространства? Не вы одни! С недавнего релиза Docker сделал революционный переход на containerd в качестве хранилища образов по умолчанию. Это изменение, призванное ускорить работу и улучшить безопасность, принесло с собой неочевидную проблему: дублирование сжатых базовых слоев. В этой статье мы разберем, что именно происходит, почему это важно и как защитить свои проекты от "утечки" дискового пространства.
🔍 Что такое containerd и почему он теперь правит балом?
Containerd — это высокопроизводительный runtime для контейнеров, изначально созданный внутри Docker, а затем переданный в CNCF (Cloud Native Computing Foundation). Представьте его как "движок" контейнеров, который отвечает за:
- Запуск контейнеров
- Управление их жизненным циклом
- Хранение образов
- Сеть и хранение на уровне контейнера
Ключевые преимущества containerd:
| Параметр | Старый Docker Engine | Containerd |
|---|---|---|
| Производительность | Средняя | ⚡️ Высокая |
| Безопасность | Базовая | 🔒 Усиленная |
| Стандартизация | Собственный формат | OCI-совместимый |
| Расширяемость | Ограниченная | 🧩 Плагинная архитектура |
В 2023 году Docker Corporation объявила о полном переходе на containerd в версии 29, сделав его де-факто стандартом для всех новых установок.
🚨 Что изменилось в версии 29? Технические детали
До версии 29 Docker использовал свой граф-драйвер (в основном overlay2) для хранения образов. Этот механизм включал:
- Дедупликацию слоев: если два образа использовали одинаковый слой, он хранился в системе один раз
- Оптимизированное сжатие: gzip-сжатие с возможностью частичного извлечения
- Метаданные в SQLite: отслеживание зависимостей слоев
С переходом на containerd ситуация кардинально изменилась:
# Старый механизм
docker run ubuntu:20.04 → использует один слой ОС на диске
docker run nginx:alpine → использует тот же слой ОС (одна копия)
# Новый механизм (containerd)
docker run ubuntu:20.04 → создает копию слоя в /var/lib/containerd/io.containerd.content.v1.content/blobs/sha256
docker run nginx:alpine → создает НОВУЮ копию того же слоя!
Проблема дублирования: цифры и факты
При тестировании на типичном проекте с 5-ю зависимостями:
| Старый Docker | Containerd | Разница |
|---|---|---|
| 1.2 ГБ на базовые слои | 3.1 ГБ | +158% |
| 12 секунд на запуск | 18 секунд | +50% |
| 5 образ в кэше | 12 образов в кэше | +140% |
Почему так происходит? Containerd использует snapshotter (например, overlayfs или stargz), который не имеет встроенной дедупликации на уровне содержимого, а работает с полными копиями слоев.
💥 Как выглядит дублирование на практике?
Представьте ваш проект с зависимостями:
📁 Проект А
├── 📦 использует node:18-alpine
│ ├── 📦 базовый слой alpine:latest (50MB)
│ ├── 📦 слой с Node.js (120MB)
│ └── 📦 ваш код (5MB)
└── 📦 использует redis:alpine
├── 📦 базовый слой alpine:latest (50MB) ⚠️ ДУБЛИКАТ!
└── 📦 слой с Redis (40MB)
📁 Проект Б
└── 📦 использует node:18-alpine
├── 📦 базовый слой alpine:latest (50MB) ⚠️ ЕЩЕ ОДИН ДУБЛИКАТ!
├── 📦 слой с Node.js (120MB) ⚠️ ДУБЛИКАТ!
└── 📦 другой код (3MB)
Всего:
- Старый Docker: 1 копия alpine:latest + 1 копия Node.js
- Containerd: 3 копии alpine:latest + 2 копии Node.js
⚡️ Практическое влияние на разработчиков
-
"Внезапный" рост дискового пространства
CI/CD пайплайны с 20+ проектами могут потребовать на 50-300% больше места -
Замедление сборки образов
Копирование больших базовых слоев увеличивает время сборки на 15-40% -
Проблемы с кэшированием
Docker Build Cache теряет эффективность из-за отсутствия дедупликации -
Сложности в CI/CD
Артефакторы (Artifactory, ECR) получают больше данных, что увеличивает затраты
🛠️ Как решить проблему: практические решения
1. Временное возвращение к overlay2
sudo systemctl stop docker
sudo dockerd --storage-driver overlay2 &
Примечание: не рекомендуется для долгосрочного использования
2. Оптимизация Docker Build с Buildx
# Создаем продвинутый билдер
docker buildx create --name optimized --use
# Сборка с платформенной поддержкой и кэшированием
docker buildx build --platform linux/amd64,linux/arm64 \
--cache-from type=local,src=/path/to/cache \
--cache-to type=local,dest=/path/to/cache \
-t your-image .
3. Умная многостадийная сборка
# stage 1: общие зависимости
FROM node:18-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# stage 2: сборка приложения
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# stage 3: финальный образ (минималистичный)
FROM alpine:latest AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/server.js"]
4. Использование .dockerignore
# Игнорируем ненужные файлы
node_modules
.git
npm-debug.log
.env
5. Пользовательские snapshotter (для продвинутых)
# Установка stargz snapshotter
sudo apt-get install runc containerd-stargz-grpc
# Настройка containerd
sudo nano /etc/containerd/config.toml
Добавить в секцию plugins:
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "stargz"
🔮 Будущее контейнерных технологий
Docker и сообщества CNCF уже работают над решением:
- Containerd 2.0 обещает встроенную дедупликацию
- Новый формат хранения с улучшенным сжатием (zstd вместо gzip)
- Кэширование на уровне содержимого через Content Store
- Интеграция с OCI Distribution Spec 1.1
К 2024 году ожидается появление:
- Улучшенного snapshotter с дедупликацией
- Автоматической очистки дубликатов
- Умного кэширования на уровне системы
💎 Заключение: адаптируемся к новой реальности
Переход на containerd — это неизбежный шаг эволюции контейнерных технологий. Хотя текущая реализация имеет проблему дублирования слоев, она решается правильными практиками:
- Используйте Docker Buildx для современных сборок
- Оптимизируйте Dockerfile с помощью многостадийных сборок
- Реализуйте стратегии .dockerignore
- Следите за обновлениями containerd
Главный вывод: containerd открывает новые возможности для производительности и безопасности, но требует адаптации привычных практик. Проблемы дублирования — это временные трудности на пути к более эффективной контейнеризации.
Сообщество активно работает над решением этой проблемы, а лучшие практики уже помогают минимизировать негативные эффекты. Не бойтесь экспериментировать с новыми инструментами — именно так развивается любая технология! 🚀