6.9 KiB
title, created, type, namespace, tags, confidence, related
| title | created | type | namespace | tags | confidence | related | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Docker data-root ↔ mount race — диагностика | 2026-09-20 | tech | personal |
|
high |
|
Docker data-root ↔ mount race
Обнаружено 2026-09-20 на Kraken (RPi5/OMV, USB-HDD). Зеркало скилла
docker-data-root-mount-race(категорияdocker-service-administration).
Триггер
Хост, у которого Docker data-root лежит на диске, монтирующемся поздно
(USB-HDD, OMV /srv/dev-disk-by-uuid-*, RPi). Признаки:
docker ps -aпусто, но контейнеры раньше были.docker info→Containers=0, при этом диск сdocker-dataсмонтирован.- После reboot сервисы в контейнерах (cloudflared, reverse-proxy bridge, jellyfin…) молча «down» — но контейнеры не удалялись.
- journal:
Duplicate entry in '/etc/fstab'?отsystemd-fstab-generator.
Механизм
dockerd стартует раньше, чем монтируется диск с его data-root. Открывает
путь, видит пусто → инициализирует пустое состояние (0 контейнеров). Через
секунды диск монтируется поверх точки, реальный containers/ появляется — но
dockerd уже разобрал состояние и не перечитывает.
Ничего не потеряно. Metadata цела на диске, daemon её просто не видит.
Причина: у docker.service нет RequiresMountsFor= на маунт-юнит диска.
Диагностика
# 1) daemon думает, что пусто
docker ps -a --format "{{.Names}}\t{{.Status}}" # пусто
docker info --format "{{.DockerRootDir}} | containers={{.Containers}}"
# 2) но metadata НА ДИСКЕ (нужен root; каталог 711 root:root)
sudo ls -la /srv/dev-disk-by-uuid-<DISK>/docker-data/
sudo ls /srv/dev-disk-by-uuid-<DISK>/docker-data/containers/ | wc -l # >0 = целы
# 3) подтвердить гонку: dockerd стартовал РАНЬШЕ диска
ps -o pid,lstart,cmd -p "$(pgrep -x dockerd)" # истинное время старта
uptime -s # время boot
sudo dmesg | grep -iE "EXT4-fs \(sd[a-z]" | tail -5 # когда ФС смонтировалась
findmnt /srv/dev-disk-by-uuid-<DISK>
# 4) подтвердить отсутствие зависимости (корень)
systemctl show docker -p RequiresMountsFor # пусто = нет порядка
grep -c "<DISK-UUID>" /etc/fstab # 2 = дубль
ПИТФОЛЛ — не то поле времени. systemctl show docker -p ExecMainStartTimestamp
может вернуть stale значение (прошлая активация). Реальное время —
ps -o lstart -p $(pgrep -x dockerd).
ПИТФОЛЛ — не тот источник RestartPolicy. RestartPolicy.Name из
docker-data/containers/<id>/hostconfig.json показывает то, что передал
исходный docker run — часто null, даже когда политика есть в живом daemon
state. НЕ делать вывод «контейнеры не поднимутся сами». Проверять живой daemon:
docker inspect <name> --format '{{.HostConfig.RestartPolicy.Name}}'
Если unless-stopped — контейнеры сами вернутся при рестарте daemon, ручной
docker start не нужен.
Фикс
Немедленный (вернуть сервисы — диск уже смонтирован)
sudo systemctl restart docker
docker info --format "containers={{.Containers}} running={{.ContainersRunning}}"
Контейнеры с restart: unless-stopped поднимаются сами.
Постоянный (сделать reboot безопасным)
- Бэкап:
/etc/fstab,/etc/docker/daemon.json, compose-каталоги сервисов → датированная папка. - Drop-in, чтобы systemd не стартовал dockerd раньше диска:
/etc/systemd/system/docker.service.d/mounts.confИмя[Unit] RequiresMountsFor=/srv/dev-disk-by-uuid-<DISK>/docker-data After=srv-dev\x2ddisk\x2dby\x2duuid\x2d<DISK>.mount.mountюнита = путь, где/→-, а каждый литеральный-escaped как\x2d(systemd escaping). sudo systemctl daemon-reload- Убрать дубль строки монтирования того же диска из
/etc/fstab(systemd отказывается от дублей; OMV часто добавляет свою рядом с ручнойUUID=...). - Проверка:
findmnt --verify --fstab # rc=0 systemctl show docker -p Requires -p After # маунт-юнит в ОБОИХ sudo systemctl restart docker # sanity: контейнеры перезагрузятся
Нельзя
- Не предполагать потерю данных, если
docker psпусто, но диск смонтирован — сначала посчитатьdocker-data/containers/.Containers=0вdocker infoне доказательство удаления. - Не
rm -rf«устаревший» docker-data — это и есть данные. - Не править
/etc/fstabчерез sed; писать полный файл локально, валидироватьfindmnt --verify --fstab, затем копировать на место.
Чеклист после фикса
docker infocount == число каталогов вdocker-data/containers/.systemctl show docker -p RequiresMountsForне пусто и указывает наdocker-data.grep -c "<DISK-UUID>" /etc/fstab=1.- После тестового
systemctl restart dockerкритичные контейнерыUp. - При следующем плановом reboot:
docker ps -q | wc -lвозвращает ожидаемое число, не0.
Применение на Kraken (2026-09-20)
Полный кейс: family/how-to/kraken-access и
personal/tech/xray-reverse-tunnel-kraken-truenas.
Кратко: boot 17:29:17, dockerd 17:31:01, диск 17:31:27 (на 26 с позже) → 0
контейнеров. Фикс: drop-in RequiresMountsFor=/srv/.../6194539b.../docker-data
- чистка fstab. Бэкап:
/home/kraken/backups/docker-recovery-20260920-105228/.