Глиф Учебники

Урок 9. Обновление и очистка места

Курс «Docker» · урок 9 из 10 · 5 минут чтения

Контейнеры работают годами, а образы тем временем обновляются: выходят исправления ошибок и уязвимостей. Старые образы, остановленные контейнеры и кэш сборки при этом копятся на диске. В этом уроке — как обновлять и как чистить, ничего не потеряв.

Обновить сам Docker

Docker из официального репозитория обновляется вместе с системой:

Bash
sudo apt update
sudo apt upgrade

При обновлении служба Docker перезапускается, а с ней — контейнеры. Контейнеры с политикой unless-stopped или always поднимутся сами; остальные придётся запустить вручную. Обновлять сервер лучше в спокойное время.

Обновить контейнер до нового образа

Работающий контейнер привязан к тому образу, из которого создан, и сам не обновится. Порядок всегда один: скачать новый образ, удалить контейнер, создать его заново с теми же ключами.

Bash
docker pull nginx:alpine
docker stop web
docker rm web
docker run -d --name web -p 8080:80 --restart unless-stopped nginx:alpine

Всё, что лежит в томах и подключённых папках, сохраняется. Всё, что было в слое контейнера, — нет; поэтому данные и держат в томах.

было nginx:alpine старая версия образа контейнер web слой записи — удалится стало nginx:alpine новая версия образа контейнер web новый пустой слой docker pull удалить и создать заново том данные в томе сохраняются
Обновление контейнера: docker pull скачивает новую версию образа, контейнер удаляют и создают заново, а том с данными подключается к новому.

С Docker Compose то же самое — две команды в папке проекта:

Bash
docker compose pull
docker compose up -d

pull скачивает свежие образы для всех сервисов, up -d пересоздаёт только те контейнеры, чей образ изменился.

Обновление в пределах тега (nginx:alpine, postgres:18) обычно безопасно: это исправления той же версии. Смена основной версии базы данных (postgres:17 → postgres:18) — отдельная работа: файлы базы новой версии часто несовместимы со старыми. Перед ней делают копию и читают инструкцию к образу.

Сколько места занимает Docker

Всё хранится в /var/lib/docker. Разбивку показывает команда:

Bash
docker system df

Столбцы: TYPE (образы, контейнеры, тома, кэш сборки), TOTAL, ACTIVE (сколько используется), SIZE (сколько занято) и RECLAIMABLE — сколько можно освободить. С ключом -v — подробно по каждому образу, контейнеру и тому.

Не удаляйте файлы в /var/lib/docker вручную. Docker ведёт им учёт, и ручное удаление ломает образы и контейнеры. Чистить нужно командами docker … prune и docker rm/rmi.

Очистка по шагам

От безопасного к опасному:

КомандаЧто удаляет
docker container pruneвсе остановленные контейнеры
docker image prune«висячие» образы — без тега и без контейнеров (остаются после обновлений и пересборок)
docker builder pruneнеиспользуемый кэш сборки образов (с -a — весь кэш)
docker image prune -aвсе образы, из которых не создан ни один контейнер
docker network pruneсети без контейнеров
docker volume pruneтома без контейнеров (по умолчанию только анонимные)

Каждая команда сначала спрашивает подтверждение (y — да); ключ -f убирает вопрос — в скриптах осторожнее с ним.

Обычная уборка после обновлений:

Bash
docker image prune
docker builder prune

Удалённый образ не страшен: при следующем docker run или docker compose up он скачается снова. Остановленный контейнер — другое дело: вместе с ним пропадают данные из его слоя.

docker container prune удаляет все остановленные контейнеры, в том числе те, что вы остановили на время и собирались запустить снова. Перед ним посмотрите список: docker ps -a --filter status=exited.

Всё сразу: docker system prune

Bash
docker system prune

Удаляет остановленные контейнеры, неиспользуемые сети, висячие образы и кэш сборки — перед этим показывает список и спрашивает подтверждение. Тома не трогает.

Более сильные варианты:

docker system prune остановленные контейнеры неиспользуемые сети висячие образы кэш сборки сначала спрашивает подтверждение + + -a ещё все образы, из которых не создано ни одного контейнера --volumes ещё неиспользуемые анонимные тома не трогает: тома без --volumes и всё, чем пользуются работающие контейнеры остановленный сервис — тоже «неиспользуемый»: его контейнер удалится
Что удаляет docker system prune без ключей, что добавляют ключи -a и --volumes и что команда не трогает.

Если сервис сейчас остановлен, его контейнер считается неиспользуемым: system prune удалит контейнер, а с -a — и образ. Ещё опаснее docker volume prune -a: он удалит все тома, к которым не подключён ни один контейнер, — например, базу данных проекта, для которого вы только что выполнили docker compose down. Перед любым prune смотрите docker ps -a и docker volume ls.

Логи растут

По умолчанию Docker хранит вывод контейнера в JSON-файле без ограничения размера. У разговорчивого сервиса за месяцы набегают гигабайты. Ограничение для всех новых контейнеров задаётся в файле /etc/docker/daemon.json (создайте его, если нет):

JSON
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Каждый контейнер будет хранить не больше трёх файлов по 10 МБ. Примените настройку:

Bash
sudo systemctl restart docker

Настройка действует только на контейнеры, созданные после неё. Уже работающие нужно пересоздать (для Compose — docker compose up -d --force-recreate). Одному контейнеру лимит можно задать при запуске: docker run --log-opt max-size=10m --log-opt max-file=3 ….

без ограничения за месяцы — гигабайты "max-size": "10m", "max-file": "3" новые строки текущий до 10 МБ до 10 МБ до 10 МБ старый удаляется не больше трёх файлов по 10 МБ на контейнер действует на контейнеры, созданные после настройки
Без ограничения лог контейнера растёт без конца, а с max-size и max-file Docker держит не больше трёх файлов по 10 МБ и удаляет самый старый.

Ошибка в daemon.json (лишняя запятая, кавычки) не даст Docker запуститься после перезапуска — вместе со всеми контейнерами. Проверьте файл перед перезапуском, например python3 -m json.tool /etc/docker/daemon.json, а после — sudo systemctl status docker.

Коротко

Проверьте себя

1. Вышла новая версия образа nginx:alpine. Как обновить работающий контейнер web?
2. Что удаляет docker image prune без ключей?
3. Что из этого docker system prune без ключей НЕ удаляет?
4. Вы добавили ограничение логов в daemon.json и перезапустили Docker. Почему старый контейнер по-прежнему пишет огромный лог?