Disk Hygiene
Зачем
Тестовый VPS
erp-test.nirbi.ruимеет всего 77GB. 2026-04-25 диск переполнился до 100% —git pullпадал сNo space left on device, контейнеры уходили вDead. Источники: 58GB build cache от повторных--no-cacherebuild’ов и неограниченные json-логи контейнеров.
Защитные меры
Две независимых страховки. Обе живут в репо erp-infrastructure.
1. Лимит логов на контейнер
В docker-compose.yml объявлен YAML-anchor x-default-logging:
x-default-logging: &default-logging
driver: json-file
options:
max-size: "50m"
max-file: "3"И применён к каждому из 17 сервисов через logging: *default-logging. Каждый контейнер не может занять логами больше 50MB × 3 ротации ≈ 150MB.
Проверка:
docker inspect erp-<service> --format '{{json .HostConfig.LogConfig}}'
# {"Type":"json-file","Config":{"max-file":"3","max-size":"50m"}}Применяется при пересоздании
Старые контейнеры (созданные до коммита
cb7b209) не подхватят лимит автоматически. Толькоdocker compose up -d --force-recreateили обычныйup -dпосле изменения compose’а пересоздаст их с новымLogConfig.
2. Ежедневный docker prune (cron)
Скрипт: erp-infrastructure/scripts/docker-cleanup.sh → копируется на VPS в /usr/local/sbin/docker-cleanup.sh.
Cron: /etc/cron.d/docker-cleanup срабатывает каждый день в 04:00 UTC.
Что делает:
docker system prune -af --filter "until=24h"— удаляет неиспользуемые образы старше сутокdocker builder prune -f --filter "until=72h"— чистит build cache старше 3 дней
Что НЕ трогает:
- Volumes (там postgres data, redis data, kafka data, minio data, certs)
- Активные образы (используются текущими контейнерами)
- Свежий build cache (последние 72ч — для быстрых итеративных билдов)
Лог: /var/log/docker-cleanup.log — каждый прогон пишет дату, занятость диска до/после, освобождённые размеры.
Установка на новом VPS
# 1. Скопировать скрипт
scp scripts/docker-cleanup.sh root@<vps>:/usr/local/sbin/
ssh root@<vps> chmod +x /usr/local/sbin/docker-cleanup.sh
# 2. Поставить cron
ssh root@<vps> 'cat > /etc/cron.d/docker-cleanup <<EOF
0 4 * * * root /usr/local/sbin/docker-cleanup.sh
EOF
chmod 644 /etc/cron.d/docker-cleanup'
# 3. Прогнать вручную для проверки
ssh root@<vps> /usr/local/sbin/docker-cleanup.sh
ssh root@<vps> cat /var/log/docker-cleanup.logЕсли диск всё-таки забился
Симптомы: git pull → No space left on device, docker compose ps показывает контейнеры в статусе Dead.
Команды восстановления (по порядку):
# 1. Посмотреть, кто занял место
df -h /
docker system df
# 2. Жёсткая очистка (НЕ трогает volumes)
docker system prune -af
docker builder prune -af
# 3. Если контейнеры в Dead state — force remove
docker rm -f $(docker ps -a -q --filter status=dead)
# 4. Пересоздать compose
cd ~/erp/erp-infrastructure
docker compose up -dНикогда не делать на проде
docker system prune -af --volumes— флаг--volumesснесёт postgres data. На тестовом VPS объём данных небольшой, но всё равно опасно. Скриптdocker-cleanup.shнамеренно не использует--volumes.
Что улучшить дальше (не сделано)
- Алерт при 85% — простой
df-чек в cron + curl в Telegram-бот. Сейчас узнаём только когда падает деплой. - GC build-cache на уровне Docker daemon —
/etc/docker/daemon.jsonс"builder": { "gc": { "defaultKeepStorage": "10GB" } }. Дублирует cron, но ловит всплески за счёт того, что Docker сам не даст кэшу разрастись > 10GB. - Убрать
--no-cacheпо умолчанию из/deploy-all— основной источник cache-разрастания. Использовать--no-cacheтолько когда подозреваем COPY-кэш-инвалидацию (Node.js с pnpm-lock.yaml).
Ссылки
- Deployment Runbook
- VPS Setup
erp-infrastructure/scripts/docker-cleanup.sh— сам скриптerp-infrastructure/docker-compose.yml—x-default-logginganchor