Как обновлять Docker-образы и безопасно заменять контейнеры

Быстрые ссылки
- Вытягивание новых образов
- Замена контейнеров через Docker Compose
- Работа с тегами образов
- Пересборка образов
- Обновление ПО внутри контейнеров
- Автоматизация обновлений контейнеров
- Заключение
Введение
Docker-контейнеры заданы как временные и легко заменяемые сущности. Когда у базового образа выходит новая версия, корректная практика — подтянуть новый образ и запустить новый экземпляр контейнера. В этой статье подробно описаны способы управления обновлениями образов на хостах и в кластерах, а также проверенные подходы, плейбуки и контрольные списки для безопасного развёртывания.
Важно: использование одного единственного подхода редко покрывает все сценарии. Комбинация декларативных инструментов, пересборок и автоматизации обычно даёт лучший результат.
Вытягивание новых образов
Базовый порядок действий при ручном обновлении:
- Вытянуть новый образ.
- Остановить и удалить контейнеры, использующие старый образ.
- Запустить новые контейнеры на базе обновлённого образа.
Пример для образа nginx:latest:
# Pull new image
docker pull nginx:latest
# Delete old container by name
docker rm example-nginx
# Start a new container
docker run -d -p 80:80 --name example-nginx nginx:latestПроблема: Docker по умолчанию не отслеживает обновления образов и не заменяет работающие контейнеры автоматически. Поэтому ручной процесс получается многословным. Его можно упростить, если использовать Docker Compose или автоматизаторы.
Замена контейнеров через Docker Compose
Docker Compose позволяет описать стек контейнеров декларативно в файле docker-compose.yml и запускать весь стек с помощью docker-compose up. Это заменяет длинные флаги docker run и делает конфигурацию воспроизводимой.
Compose имеет команду pull, чтобы подтянуть обновлённые версии всех образов стека. После этого нужно перезапустить стек, чтобы контейнеры были пересозданы на базе новых образов.
# Pull all images in the stack
docker-compose pull
# Restart the stack
# If a new image version has been pulled, containers
# using the old tag will be replaced with new instances.
docker-compose up -dУпрощение: можно объединить команды в shell-алиас:
alias composePullUp="docker-compose pull && docker-compose up -d"Преимущества Docker Compose:
- Декларативность: вы храните конфигурацию в YAML и не забываете флаги.
- Масштабируемость: один файл — один стек.
- Повторяемость действий на разных хостах.
Ограничения:
- Процесс всё ещё двухступенчатый (pull + up).
- Для сложных оркестраций лучше использовать Kubernetes или Docker Swarm.
Работа с тегами образов
Тег — это явная ссылка на версию образа. При ручном pull вы указываете тег. Docker Compose берёт тег из docker-compose.yml.
Важно понимать семантику тегов автора образа:
- Тег вида node:14 обычно означает последнюю патч-версию внутри ветки 14.x.
- Тег node:latest укажет на самую новую мажорную версию (иногда это 16, 18 и т.д.).
Если старый контейнер использовал node:latest, подтягивание образа и пересоздание контейнера может вызвать внезапный мажорный апгрейд Node.js внутри контейнера. Поэтому в production обычно фиксируют теги до мажорной версии или до конкретного патча и контролируют обновления через CI/CD.
Рекомендации по тегам:
- В production используйте семантические теги (например, 1.4.2) или мажорные (например, 14).
- Для критичных сервисов внедрите тестовую стадию, где автоматически проверяются новые версии образов.
- Не полагайтесь лишь на :latest в продакшн-средах.
Пересборка образов
Если вы строите собственные образы (docker build), их нужно пересобирать, когда меняется базовый образ.
Пересборка с подтягиванием базового образа:
docker build --pull -t my-image:latest .Затем замените контейнеры:
# Delete old container by name
docker rm my-container
# Start a new container
docker run -d --name my-container my-image:latestФлаг –pull в docker build заставляет Docker подтянуть базовый образ, указанный в Dockerfile. Без него Docker использует локально кешированный образ, что может скрыть обновления.
С Compose эквивалент:
docker-compose build --pull
docker-compose up -dCompose упрощает процесс, потому что вы забываете про конкретные имена и теги — Compose сам пересоберёт слои поверх новых базовых образов и пересоздаст контейнеры.
Обновление ПО внутри контейнеров
Коротко: не редактируйте контейнеры вручную в продакшне.
Причина: контейнеры — это иммутабельные инстансы. Запуск apt-get upgrade внутри работающего контейнера ломает принцип воспроизводимости. Такие изменения теряются при пересоздании контейнера.
Исключение: во время построения образа (в Dockerfile) вы можете запускать обновления пакетов, чтобы получить последние патчи на момент сборки:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y ...Правильная практика: пересобирайте образ и пересоздавайте контейнеры. Для короткоживущих контейнеров избегайте постоянных изменений файловой системы контейнера; храните данные во внешних volume.
Автоматизация обновлений контейнеров
Сторонние проекты помогают автоматизировать проверку обновлений тегов и перезапуск контейнеров. Популярный инструмент — Watchtower. Он мониторит работающие контейнеры и заменяет их при обнаружении новых версий образов в Docker Hub или в приватных реестрах.
Развёртывание Watchtower как контейнера:
docker run -d -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtowerКак это работает:
- Watchtower монтирует Docker socket хоста и вызывает Docker API.
- Когда в реестре появляется новый образ, Watchtower подтягивает его и пересоздаёт контейнеры с теми же флагами, которые использовались при запуске.
Работа с приватными регистрами
По умолчанию Watchtower ориентирован на Docker Hub. Для приватных регистров требуется передать учётные данные.
Создайте JSON-файл с содержимым:
{
"auths": {
"example.com": {
"auth": "credentials"
}
}
}Где example.com — адрес вашего регистра. Сгенерируйте строку credentials командой:
echo -n 'username:password' | base64Вставьте результат в поле auth. Затем смонтируйте файл в контейнер Watchtower:
docker run -d
-v config.json:/config.json
-v /var/run/docker.sock:/var/run/docker.sock
containrrr/watchtowerВажно: храните секреты безопасно. Вместо монтирования плоского файла можно использовать секреты Docker или менеджеры секретов вашей платформы.
Плейбук по безопасному обновлению образов (SOP)
Минимальный пошаговый плейбук для обновления сервисов:
- Проверка исходного состояния
- Подтвердите версии текущих образов и работающие контейнеры.
- Зафиксируйте критичные метрики и логи.
- Тестирование в staging
- Подтяните образ в staging.
- Автоматические тесты: smoke, интеграция, e2e.
- Подтягивание и пересборка
- Для сторонних образов: docker pull
: . - Для собственных: docker build –pull -t my-image:tag .
- Для сторонних образов: docker pull
- Развёртывание в canary/blue-green
- Запустите обновлённый экземпляр параллельно.
- Наблюдайте 15–60 минут (время зависит от сервиса).
- Проверка и переключение трафика
- Если всё хорошо — переключите трафик на новые инстансы.
- Если появились проблемы — откатите изменения.
- Документация
- Зафиксируйте использованные теги и время обновления.
Критерии приёмки
- Сервисы проходят все smoke-тесты.
- Нагрузка на новые инстансы находится в ожидаемых пределах.
- Нет новых ошибок уровня ERROR/FATAL в ключевых логах.
Критерии отката
- Непроходимые тесты функциональности.
- Значительное ухудшение времени ответа (>30–50% от baseline).
- Увеличение ошибок, приводящих к падению сервиса.
Риск-матрица и меры по снижению рисков
- Непреднамеренный мажорный апгрейд
- Риск: высокая
- Митигатор: фиксируйте теги, не используйте :latest в продакшн
- Баги в новом образе
- Риск: средний
- Митигатор: staging, canary, автоматические тесты
- Неавторизованный доступ к учётным данным регистра
- Риск: высокий
- Митигатор: хранение секретов в менеджере секретов, ограниченный доступ
Роли и чеклисты
DevOps-инженер
- Обеспечить CI-сборку с –pull флагом
- Настроить окружения staging/canary
- Настроить бэкапы и мониторинг
Разработчик
- Обновлять зависимости и фиксировать теги
- Писать тесты для регрессий
- Участвовать в тестировании в staging
Инженер по безопасности
- Проверять образы на CVE
- Настроить сканеры образов в CI
- Контролировать доступ к регистрам и секретам
Release Manager
- Планировать окна обновлений
- Координировать тестирование и откат
- Документировать версии и инциденты
Примеры альтернативных подходов
- Kubernetes: автоматически перезапускает поды при обновлении образов через деплоймент; даёт стратегии развёртывания (rolling, canary, blue-green).
- Docker Swarm: встроенные механизмы обновления сервисов.
- CI/CD-ориентированная модель: образы пересобирать и деплоить из pipeline; избегать ручных действий на хостах.
Когда автоматизация не подходит
- Маленькие одноразовые тестовые хосты, где ручной контроль проще.
- Если инфраструктура не допускает монтирования Docker socket по соображениям безопасности.
Противопоказания и примеры неработоспособности
Контейнерные приложения с локальными изменениями файловой системы (без volumes) не воспроизводимы после пересоздания. В таких случаях автоматическая замена контейнера приведёт к потере данных. Всегда выносите состояние в volumes или внешние сервисы.
Шаблон команды для безопасного обновления в продакшн
- Проверить текущие контейнеры:
docker ps --format "{{.Names}} {{.Image}} {{.Status}}"- Подтянуть образ:
docker pull my-image:1.2.3Тестирование локально / в staging.
Пересоздать контейнер:
docker stop my-container && docker rm my-container
docker run -d --name my-container my-image:1.2.3Или с Compose:
docker-compose pull && docker-compose up -dБезопасность и лучшие практики
- Не монтируйте /var/run/docker.sock в произвольный контейнер без контроля — это даёт привилегированный доступ к Docker API.
- Используйте чтение только необходимого уровня доступа к приватным регистрам.
- Сканируйте образы на уязвимости в CI-пайплайне.
- Подписывайте образы (notary/COSIGN) для целостности и аутентичности.
Decision flow для обновления образа
flowchart TD
A[Новая версия образа доступна?] -->|Да| B{Это внешний образ?}
B -->|Да| C[Ручное тестирование или staging]
B -->|Нет| D[Пересобирать образ с --pull]
C --> E{Тесты пройдены?}
D --> E
E -->|Да| F[Запустить canary/blue-green]
F --> G{Мониторинг OK?}
G -->|Да| H[Переключить трафик на новые инстансы]
G -->|Нет| I[Откат к предыдущей версии]
E -->|Нет| I
A -->|Нет| Z[Оставить как есть]1-строчный глоссарий
- Образ: упакованная файловая система и метаданные приложения.
- Контейнер: запущенный инстанс образа.
- Тег: метка версии образа.
- Compose: инструмент для декларативного описания стека контейнеров.
- Watchtower: инструмент для автоматической замены контейнеров при обновлении образов.
Заключение
Docker сам по себе не обновляет работающие контейнеры при появлении новых образов. Варианты решения:
- Ручной подход с docker pull и пересозданием контейнеров.
- Декларативный подход с docker-compose (pull + up).
- Полная автоматизация с помощью Watchtower или CI/CD (предпочтительно для частых деплоев).
Выбор зависит от масштаба инфраструктуры, требований безопасности и зрелости процессов. Независимо от подхода, внедряйте стадию тестирования, стратегию развёртывания (canary/blue-green) и чёткий плейбук отката.
Важно: если ваша организация уже собирает и деплоит образы из CI при каждом коммите, убедитесь, что сборки выполняются с –pull, чтобы включать свежие патчи базовых образов.