SystemdDoctor
docker.service контейнерычастое

Docker в systemd: почему демон не поднимается

Демон Docker в systemd устроен нетипично: рядом с docker.service есть docker.socket, а параметры запуска частично берутся из /etc/docker/daemon.json. Большинство отказов — это ошибка в этом файле или конфликт между способом указания адреса в файле и в unit-файле.

О службе

Первое, что стоит знать: Docker отказывается стартовать при синтаксической ошибке в daemon.json. Проверить файл можно любым разборщиком JSON — сам Docker в журнале печатает строку с ошибкой, но не всегда очевидно.

Второе: адрес прослушивания задаётся либо ключом -H в unit-файле, либо параметром hosts в daemon.json, но не двумя способами одновременно. При конфликте демон завершается с сообщением о том, что адрес указан дважды. Это одна из самых частых поломок после ручной правки.

Третье: Docker сильно зависит от контрольных групп и от версии их иерархии. На системах со смешанной иерархией и в необычных окружениях демон может не запуститься вовсе или запуститься без части возможностей ограничения ресурсов.

Как устроена

Связанные unitdocker.service и docker.socket, а также containerd.service
Файл настроек/etc/docker/daemon.json — ошибка в нём не даёт демону стартовать
Адрес прослушиваниязадаётся либо через -H в unit, либо через hosts в daemon.json; одновременно нельзя
Каталог данных/var/lib/docker — растёт быстро, переполнение раздела останавливает демон
Зависимостьдемон требует работающий containerd; его состояние стоит проверять вместе с docker

Частые ошибки

32 записи базы отмечены за этой службой.

Коды выхода

  • status=1/FAILURE в systemdКод 1/FAILURE означает, что программа запустилась и сама завершилась с ошибкой. Как найти настоящую причину в журнале службы.
  • status=219/CGROUP в systemdКод 219/CGROUP: не удалось создать или настроить контрольную группу службы. Причины на уровне системы и контейнеров.
  • status=226/NAMESPACE в systemdКод 226/NAMESPACE: не удалось настроить пространства имён монтирования, UTS или IPC. Частая причина — путь в ReadOnlyPaths= или ProtectHome=.
  • status=200/CHDIR в systemdКод 200/CHDIR означает, что systemd не смог перейти в каталог из WorkingDirectory= до запуска программы. Причины и решение.
  • status=203/EXEC в systemdКод 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
  • status=216/GROUP в systemdКод 216/GROUP: systemd не смог определить или сменить группу из Group= или SupplementaryGroups=. Причины и как проверить.
  • status=225/NETWORK в systemdКод 225/NETWORK: не удалось создать сетевое пространство имён для службы при PrivateNetwork=yes или NetworkNamespacePath=.
  • status=228/SECCOMP в systemdКод 228/SECCOMP: не удалось применить фильтр системных вызовов из SystemCallFilter=. Причины: неизвестное имя вызова, отсутствие поддержки в ядре.

Ресурсы и ограничения

Сообщения журнала

  • Address already in use при запуске службыПорт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
  • Permission denied в журнале службыОтказ в доступе у службы systemd: права на файл, каталоги по пути, пользователь службы, параметры изоляции, SELinux и AppArmor.
  • Function not implemented в контейнереОшибка 38 при системном вызове: вызов запрещён фильтром или отсутствует в окружении. Разбор для контейнеров.
  • No such file or directory в журнале службыСлужба не находит файл или каталог. Разбор: путь, момент запуска, изоляция unit-файла, символические ссылки, приватный /tmp.
  • Read-only file system в журнале службыСлужба не может писать: файловая система только для чтения. Разбор: параметры изоляции unit, монтирование ro, ошибки файловой системы.
  • Порт занят, но процесса не видноАдрес занят, а инструменты не показывают владельца: другое сетевое пространство имён, контейнер, сокет systemd.

Зависимости и порядок

Состояния результата

  • Failed with result 'oom-kill'Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
  • Failed with result 'timeout'Состояние timeout: служба не уложилась в отведённое время при запуске, остановке или перезагрузке настроек.
  • Job for … failed because a timeout was exceededЗадание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.

Сигналы

  • signal=KILL (status=9/KILL) в systemdПроцесс службы убит сигналом KILL. Кто мог его послать: OOM-killer, таймаут остановки systemd, администратор.
  • signal=SYS (status=31/SYS) в systemdПроцесс службы убит сигналом SYS: фильтр системных вызовов запретил вызов. Как найти запрещённый вызов и исправить SystemCallFilter.
  • signal=TERM (status=15/TERM) в systemdПроцесс службы завершён сигналом TERM. Когда это нормальная остановка, а когда признак проблемы.

Ошибки служб

Коды выхода этой службы

Числа в status=N ниже 200 назначает сама программа, 200 и выше — systemd, когда не смог подготовить запуск.

statusЧто означает у этой службыКуда смотреть
1/FAILURE ошибка в daemon.json или конфликт параметров адреса. разбор
219/CGROUP проблемы с иерархией контрольных групп — обычно во вложенном контейнере. разбор

Диагностика

Docker без containerd не работает: проверять нужно оба unit.

systemctl status docker --no-pager -l && systemctl status containerd --no-pager | head -8

Проверка синтаксиса файла настроек: самая частая причина отказа.

sudo python3 -c "import json;json.load(open('/etc/docker/daemon.json'))" && echo JSON в порядке

Сообщения демона с точной причиной завершения.

journalctl -u docker -n 60 --no-pager

Разбор настроек демоном без запуска (в новых версиях).

sudo dockerd --validate 2>&1 | head

Место под образы и контейнеры: переполнение останавливает демон.

df -h /var/lib/docker

Параметры unit, которые тут важны

  • Type=notify: демон сообщает systemd о готовности
  • ExecReload=перезагрузка настроек сигналом HUP без остановки контейнеров
  • LimitNOFILE=демону нужно много дескрипторов при большом числе контейнеров
  • TasksMax=контейнеры создают много процессов; предел задач у службы должен это учитывать
  • KillMode=в unit Docker обычно process: остановка демона не убивает контейнеры

Частые вопросы

В журнале «unable to configure the Docker daemon with file /etc/docker/daemon.json». Что это?

Ошибка разбора файла настроек: либо неверный JSON, либо неизвестный ключ. Сообщение обычно содержит имя ключа или позицию в файле.

Демон не стартует после добавления -H в unit-файл. Почему?

Скорее всего адрес уже задан в daemon.json ключом hosts. Уберите один из способов: одновременно они конфликтуют.

Источники