docker stop, rm, prune
Поднимать контейнеры легко. Прибирать за собой — отдельный навык. Если ты не следишь, через месяц у тебя на диске будут десятки exited контейнеров, сотни orphaned image-слоёв, и куча неиспользуемых volumes. На mac, где VM имеет ограниченный диск, это особенно болезненно.
В этом уроке: как корректно останавливать контейнеры (с разницей stop vs kill), как удалять, и как массово чистить мусор через prune.
docker stop — корректная остановка
docker stop pg
Что физически происходит:
- Docker daemon посылает SIGTERM главному процессу контейнера (PID 1).
- Daemon ждёт 10 секунд.
- Если процесс не завершился — посылает SIGKILL.
- Контейнер переходит в state
exitedс exit code (130 для SIGTERM, 137 для SIGKILL).
SIGTERM — это «вежливый» сигнал: «пожалуйста, заверши работу как следует». Хорошо написанный сервис (Postgres, Redis, nginx) ловит SIGTERM и делает graceful shutdown: дописывает буферы, закрывает соединения, флашит данные.
SIGKILL — это «жёсткое» убийство, которое процесс не может игнорировать. Это плохо для stateful сервисов — Postgres может остаться с inconsistent WAL, придётся recovery при старте.
Поэтому в норме мы хотим SIGTERM с timeout’ом. Если ты знаешь, что твой сервис долго закрывается (например, ETL job, который дописывает batch), увеличь timeout:
docker stop --time=60 pg
# даём 60 секунд на graceful shutdown
docker kill — без вежливости
docker kill pg
Сразу посылает SIGKILL (без SIGTERM, без timeout). Контейнер падает мгновенно.
Когда полезно:
- Контейнер завис и не отвечает на
stop. - Тестовая среда, нет состояния.
- Тебе нужен быстрый выход.
Когда плохо:
- Любой stateful сервис (Postgres, Kafka, MinIO). Можно потерять данные.
Опционально другие сигналы через -s:
docker kill -s SIGHUP nginx # перечитать конфиг
docker rm — удалить контейнер
docker rm pg
Удаляет контейнер из системы. После этого контейнер больше не существует — его нет в docker ps -a, его логи стёрты, его writable layer удалён.
Контейнер можно удалить только если он остановлен. Запущенный контейнер удалить нельзя — Docker откажет:
Error response from daemon: cannot remove container <id>: container is running
Решения:
- Сначала
docker stop, потомdocker rm:
docker stop pg
docker rm pg
- Или force через
-f:
docker rm -f pg
-f — это docker kill + docker rm. Удобно, но небезопасно для stateful сервисов.
Что удаляется вместе с контейнером
- Writable layer контейнера (изменения, сделанные внутри).
- Логи контейнера.
- Привязки к network bridges.
Что не удаляется:
- Образ, из которого был контейнер — он остаётся.
- Named volumes — они остаются (это важно! данные сохранены).
- Bind mount директории на хосте.
docker container prune — массово удалить остановленные
docker container prune
Удаляет все контейнеры в состоянии exited / dead. Спросит подтверждение:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
abc123...
def456...
Total reclaimed space: 124MB
Без подтверждения — флаг -f:
docker container prune -f
Это типичный шаг после интенсивной dev-сессии: очистить остановленные контейнеры.
С фильтром можно удалить только старые:
docker container prune --filter "until=24h"
# удалит контейнеры, остановленные более 24 часов назад
docker image prune — мусорные образы
После сборок и pull’ов накапливаются неиспользуемые образы. Их две категории:
- Dangling — образы без тегов, на которые ничего не ссылается. Получаются от незавершённых build’ов или пересборок (старая версия теперь имеет тег
<none>). - Unused — образы, которые есть локально, но из них не запущен ни один контейнер.
# Только dangling
docker image prune
# Все unused (более агрессивно)
docker image prune -a
Второй вариант часто сэкономит много места. На dev-машине образы накапливаются быстро — postgres:13, 14, 15, 16 и все pull’ы, которые ты делал.
docker volume prune — забытые volumes
docker volume prune
Удаляет volumes, которые не привязаны ни к одному контейнеру.
ВНИМАНИЕ: volume prune удаляет данные. Если у тебя в volume лежит твоя локальная Postgres-база с важными dev-данными, и нет работающего контейнера, который её использует — она будет удалена. Сначала всегда проверь: docker volume ls.
docker system prune — большая уборка
docker system prune
Эта команда чистит сразу:
- Все остановленные контейнеры.
- Все dangling образы.
- Неиспользуемые networks.
- Build cache.
docker system prune -a
Дополнительно: все unused образы (не только dangling).
docker system prune -a --volumes
Дополнительно: все unused volumes. Это самая агрессивная команда — после неё на диске остаётся только то, что прямо сейчас используется.
docker system df — сколько занято
Перед уборкой полезно посмотреть, что у тебя занимает место:
docker system df
Пример вывода:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 47 8 12.3 GB 9.1 GB (74%)
Containers 23 4 512 MB 498 MB (97%)
Local Volumes 12 3 3.2 GB 2.8 GB (87%)
Build Cache 156 0 4.7 GB 4.7 GB
RECLAIMABLE — сколько можно освободить через prune. Здесь видно, что 9 ГБ images + 4.7 ГБ build cache можно убрать.
С -v (verbose) — детально по каждому образу/контейнеру:
docker system df -v
Восстановление диска на mac (специфика)
На mac контейнеры и образы живут в VM, которая представлена одним большим виртуальным диском. Этот диск растёт по мере использования, но не сжимается обратно автоматически после prune.
После docker system prune место освобождается внутри VM, но размер виртуального диска не уменьшается. Чтобы реально вернуть место на хост-mac:
- Docker Desktop: Settings -> Resources -> Advanced -> “Clean / Purge data” или уменьшить Disk image size (с пересозданием VM).
- OrbStack:
orb info disks— посмотреть размер.orb purge— пересоздать VM с нуля.
Это редкая, но важная процедура — раз в полгода полезно «фактически» вернуть место.
Попробуй сам
# 1. Запусти несколько контейнеров
docker run --rm hello-world
docker run --rm hello-world
docker run -d --name temp1 nginx
docker run -d --name temp2 redis:alpine
# 2. Посмотри состояние
docker ps -a
docker system df
# 3. Останови (graceful)
docker stop temp1 temp2
# 4. Удали
docker rm temp1 temp2
# 5. Глобально подчистись
docker container prune -f
docker image prune -f
# 6. Большая уборка (осторожно — удаляет всё неиспользуемое!)
# docker system prune -a -f --volumes
# 7. Проверь
docker system df
Обрати внимание, как меняется размер RECLAIMABLE после каждого prune.
Связь с дальнейшими модулями
- Модуль 08 (volumes): подробнее про
docker volume. Очень аккуратно сvolume prune— это удаление данных. - Модуль 13 (debug): иногда не удалять контейнер — это часть стратегии дебага. Сначала логи и inspect, потом rm.
- Модуль 17 (CI): в CI важно, чтобы build cache не разрастался — там
docker system prune -f --filter "until=72h"в cron’е.