1.3. Docker daemon
Цели
После этого материала вы сможете:
- объяснить архитектуру daemon–client и то, почему CLI сам ничего не запускает;
- управлять службой Docker через
systemctl: статус, запуск, остановка, перезапуск, автозагрузка; - объяснить роль
docker.socketи механизм socket activation; - читать логи daemon через
journalctlи находить в них причину проблемы; - настраивать daemon через
/etc/docker/daemon.jsonи проверять конфигурацию до перезапуска; - объяснить, что произойдёт с работающими containers при перезапуске daemon;
- понимать назначение каталога
/var/lib/dockerи его структуру.
Предварительные знания
- 1.2. Установка Docker Engine — Docker установлен;
- базовое понимание системных служб.
Ключевые термины
| Термин | Объяснение |
|---|---|
daemon | Фоновый процесс, работающий без привязки к терминалу. В нашем случае — dockerd |
systemd | Система инициализации и менеджер служб в большинстве современных дистрибутивов Linux |
unit | Единица управления в systemd: служба, сокет, таймер и другие. Описывается unit-файлом |
socket activation | Механизм systemd, при котором сокет создаётся заранее, а служба запускается при первом обращении к нему |
journalctl | Инструмент чтения журнала systemd, куда пишут логи все службы |
drop-in | Файл переопределения настроек unit без изменения оригинального unit-файла |
live restore | Режим, при котором containers продолжают работать во время перезапуска daemon |
Теория
Архитектура daemon–client
Команда docker ничего не запускает сама. Она формирует HTTP-запрос и отправляет его daemon через Unix socket. Daemon выполняет работу и возвращает ответ.
пользователь
│ docker run nginx
▼
┌──────────────┐ HTTP over Unix socket ┌──────────────┐
│ docker CLI │ ───────────────────────────► │ dockerd │
│ │ ◄─────────────────────────── │ (daemon) │
└──────────────┘ JSON-ответ └──────┬───────┘
│ gRPC
▼
┌──────────────┐
│ containerd │
└──────────────┘
Из этой схемы следуют три практических вывода.
Первый. CLI и daemon — разные программы, которые могут иметь разные версии. Именно поэтому docker version показывает два блока. Обычно версии совпадают, но CLI может подключаться и к удалённому daemon другой версии.
Второй. Всё, что делает Docker, выполняется от имени root (в обычном режиме). Пользователь, способный отправлять команды daemon, фактически имеет права root на машине. Этому посвящён урок 1.5.
Третий. Если daemon не работает, CLI бесполезен. Диагностика проблем начинается с проверки daemon.
Два unit-файла: service и socket
Установка создаёт два unit:
| Unit | Назначение |
|---|---|
docker.service | Сам daemon dockerd |
docker.socket | Unix socket /var/run/docker.sock с socket activation |
Socket activation означает: systemd создаёт и слушает socket сам, а docker.service запускается при первом обращении к нему. Это ускоряет загрузку системы — daemon не стартует, пока не понадобится.
Практическое следствие, которое сбивает с толку: команда
sudo systemctl stop docker
останавливает docker.service, но docker.socket продолжает слушать. Первое же обращение через docker ps запустит daemon обратно. Чтобы остановить Docker по-настоящему, нужно остановить оба unit.
Что происходит с containers при перезапуске daemon
Ответ зависит от настройки live-restore.
По умолчанию (live-restore выключен): при остановке daemon все работающие containers останавливаются. При старте daemon containers с restart policy always или unless-stopped запускаются заново.
С live-restore: true: containers продолжают работать во время перезапуска daemon. Это возможно благодаря архитектуре с shim-процессами: каждый container имеет собственный containerd-shim, который является его родителем и не зависит от dockerd. Механизм подробно разбирается в разделе 17.
Ограничения live-restore: не работает при изменении части настроек daemon и несовместим со Swarm mode.
Конфигурация через daemon.json
Файл /etc/docker/daemon.json задаёт настройки daemon. По умолчанию его не существует — Docker работает с настройками по умолчанию.
Наиболее полезные параметры для курса:
| Параметр | Назначение |
|---|---|
log-driver, log-opts | Драйвер логирования и ротация. Разбирается в разделе 13 |
data-root | Каталог данных вместо /var/lib/docker |
default-address-pools | Диапазоны адресов для создаваемых сетей. Разбирается в разделе 08 |
live-restore | Сохранение containers при перезапуске daemon |
features | Включение возможностей, например containerd-snapshotter |
debug | Подробное логирование |
Важное правило: изменения применяются только после перезапуска или перечитывания конфигурации. Синтаксическая ошибка в JSON приводит к тому, что daemon не стартует. Поэтому файл нужно проверять до перезапуска.
Каталог данных
По умолчанию /var/lib/docker. Структура зависит от того, какое хранилище образов используется.
/var/lib/docker/
├── buildkit/ кэш сборки BuildKit
├── containers/ метаданные и логи containers
├── image/ метаданные образов (классическое хранилище)
├── network/ конфигурация сетей
├── overlay2/ слои образов и writable layers
├── plugins/ плагины
├── volumes/ данные named volumes
└── tmp/
При использовании containerd image store образы хранятся в /var/lib/containerd, а /var/lib/docker содержит остальное.
Не редактируйте содержимое этих каталогов вручную. Метаданные и файлы связаны между собой; ручное удаление приводит к несогласованному состоянию, которое чинится только полной переустановкой. Для очистки используйте команды Docker — см. раздел 13.
Внутренний механизм
Последовательность запуска
- systemd активирует
docker.socketи создаёт/var/run/docker.sockс владельцемroot, группойdockerи правами0660. - При первом обращении к сокету systemd запускает
docker.service. dockerdчитает/etc/docker/daemon.json(если файл существует) и аргументы из unit-файла.- Daemon проверяет доступность механизмов ядра, выбирает storage driver, инициализирует сеть.
- Daemon подключается к
containerd(запускается как отдельная службаcontainerd.service). - Daemon восстанавливает состояние containers из метаданных.
- Containers с подходящей restart policy запускаются.
Если любой шаг не удался, dockerd завершается с ошибкой, и systemd помечает unit как failed. Причина всегда есть в журнале.
Конфликт аргументов daemon.json и unit-файла
Частая ловушка. Unit-файл содержит строку запуска:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Если тот же параметр задать и в daemon.json (например, hosts), daemon откажется стартовать с ошибкой о конфликте. Правило: параметр задаётся либо в daemon.json, либо в аргументах — но не в обоих местах.
Для изменения аргументов запуска используется drop-in файл, а не редактирование /lib/systemd/system/docker.service (он перезапишется при обновлении пакета).
Команды и примеры
Статус службы
systemctl status docker
Ожидаемый результат:
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Wed 2026-07-29 10:12:44 MSK; 2h 5min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 1842 (dockerd)
Tasks: 21
Memory: 118.4M
CPU: 4.312s
CGroup: /system.slice/docker.service
└─1842 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Что читать в этом выводе:
| Поле | Значение |
|---|---|
Loaded: ... enabled | Служба запускается автоматически при загрузке системы |
Active: active (running) | Служба работает |
TriggeredBy: docker.socket | Активирована через socket activation |
Main PID | PID процесса dockerd |
CGroup | Строка запуска с фактическими аргументами |
Команда не требует sudo для чтения статуса.
Управление службой
sudo systemctl stop docker
Что делает: останавливает docker.service. Работающие containers будут остановлены (при выключенном live-restore).
Важно: docker.socket продолжает работать, и любая команда docker запустит daemon заново. Для полной остановки:
sudo systemctl stop docker.socket docker.service
sudo systemctl start docker
Запускает daemon.
sudo systemctl restart docker
Перезапускает. Используется после изменения daemon.json.
sudo systemctl reload docker
Перечитывает часть конфигурации без перезапуска daemon и без остановки containers. Работает не для всех параметров — например, изменение data-root требует полного перезапуска.
Автозагрузка:
sudo systemctl disable docker.service docker.socket # отключить
sudo systemctl enable docker.service docker.socket # включить
Что изменяет: создаёт или удаляет символические ссылки в /etc/systemd/system/. Не влияет на текущее состояние службы.
Логи daemon
sudo journalctl -u docker.service
Весь журнал службы с начала.
Практически полезные варианты:
# последние 50 строк
sudo journalctl -u docker.service -n 50
# следить в реальном времени
sudo journalctl -u docker.service -f
# за последний час
sudo journalctl -u docker.service --since "1 hour ago"
# только ошибки
sudo journalctl -u docker.service -p err
# без сокращения длинных строк
sudo journalctl -u docker.service --no-pager -o cat
Разбор флагов:
| Флаг | Значение |
|---|---|
-u | Фильтр по unit |
-n N | Последние N строк |
-f | Следовать за новыми записями (как tail -f) |
--since | Начиная с момента времени; принимает и абсолютные даты, и выражения вроде 10 min ago |
-p err | Приоритет не ниже err |
-o cat | Только текст сообщения, без метаданных |
Не путайте
journalctl -u docker.service(логи самого daemon) иdocker logs <container>(логи приложения внутри container). Это разные источники. Логи приложения разбираются в разделе 13.
Настройка daemon.json
Создание файла:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null <<'EOF'
{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true
}
EOF
Что делает эта конфигурация:
log-driver: local— использовать драйверlocalвместоjson-file. Он эффективнее по месту и по умолчанию выполняет ротацию;max-size: 10m,max-file: 3— не более трёх файлов по 10 MB на container, то есть максимум 30 MB логов;live-restore: true— containers переживают перезапуск daemon.
Проверка синтаксиса до перезапуска. Если в файле ошибка, daemon не стартует, и вы останетесь без Docker. Проверьте JSON заранее:
python3 -m json.tool /etc/docker/daemon.json
Команда выведет отформатированный JSON при корректном синтаксисе и сообщение об ошибке с номером строки при некорректном.
Дополнительная проверка средствами самого Docker — запуск daemon в режиме валидации:
sudo dockerd --validate
configuration OK
Применение изменений:
sudo systemctl restart docker
sudo docker info --format '{{.LoggingDriver}}'
local
Изменение аргументов запуска через drop-in
sudo systemctl edit docker.service
Открывается редактор. Впишите:
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --debug
Пустая строка ExecStart= обязательна: она сбрасывает значение из оригинального unit-файла. Без неё systemd попытается выполнить обе команды и откажет.
Применение:
sudo systemctl daemon-reload
sudo systemctl restart docker
Просмотр итоговой конфигурации:
systemctl cat docker.service
Отмена изменений:
sudo systemctl revert docker.service
sudo systemctl daemon-reload
sudo systemctl restart docker
Просмотр каталога данных
sudo docker info --format '{{.DockerRootDir}}'
/var/lib/docker
Объём:
sudo du -sh /var/lib/docker
Структурированный отчёт средствами Docker:
sudo docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 12 3 2.841GB 1.902GB (66%)
Containers 5 2 12.4MB 8.1MB (65%)
Local Volumes 4 2 318.2MB 102.4MB (32%)
Build Cache 47 0 1.204GB 1.204GB
Эта команда безопаснее du: она показывает, что именно занимает место и сколько можно освободить.
Практический пример
Задача: настроить ротацию логов, убедиться, что настройка применилась, и уметь откатить изменение.
daemon-config/
├── daemon.json
└── apply.sh
daemon.json
{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true
}
apply.sh
#!/usr/bin/env bash
# apply.sh — безопасное применение конфигурации Docker daemon.
set -euo pipefail
CONFIG_SRC="$(dirname "$0")/daemon.json"
CONFIG_DST="/etc/docker/daemon.json"
BACKUP="/etc/docker/daemon.json.bak"
echo "1. Проверка синтаксиса JSON..."
python3 -m json.tool "$CONFIG_SRC" > /dev/null
echo " OK"
echo "2. Резервная копия текущей конфигурации..."
if [ -f "$CONFIG_DST" ]; then
sudo cp "$CONFIG_DST" "$BACKUP"
echo " Сохранено в $BACKUP"
else
echo " Текущей конфигурации нет — создаётся впервые"
fi
echo "3. Установка новой конфигурации..."
sudo mkdir -p /etc/docker
sudo cp "$CONFIG_SRC" "$CONFIG_DST"
echo "4. Валидация средствами dockerd..."
sudo dockerd --validate
echo "5. Перезапуск daemon..."
sudo systemctl restart docker
echo "6. Проверка применённых настроек..."
driver="$(sudo docker info --format '{{.LoggingDriver}}')"
echo " Logging driver: $driver"
if [ "$driver" = "local" ]; then
echo
echo "Готово."
else
echo
echo "Настройка не применилась. Проверьте: sudo journalctl -u docker.service -n 30"
exit 1
fi
Запуск:
chmod +x apply.sh
./apply.sh
Откат:
sudo cp /etc/docker/daemon.json.bak /etc/docker/daemon.json
sudo systemctl restart docker
Проверка результата
sudo docker info --format 'Driver: {{.LoggingDriver}} LiveRestore: {{.LiveRestoreEnabled}}'
Driver: local LiveRestore: true
Проверка, что daemon перезапустился без ошибок:
systemctl is-active docker
active
Типичные ошибки
| Ошибка | Причина | Исправление |
|---|---|---|
После systemctl stop docker команда docker ps снова запускает daemon | Работает socket activation через docker.socket | Остановить оба unit: sudo systemctl stop docker.socket docker.service |
Daemon не стартует после правки daemon.json | Синтаксическая ошибка JSON (лишняя запятая, кавычки) | python3 -m json.tool /etc/docker/daemon.json, исправить, перезапустить |
unable to configure the Docker daemon ... conflicting options | Один параметр задан и в daemon.json, и в ExecStart | Убрать дублирование из одного из мест |
Изменения в /lib/systemd/system/docker.service пропали после обновления | Файл принадлежит пакету и перезаписывается | Использовать systemctl edit docker.service |
systemctl edit не сработал | Забыта пустая строка ExecStart= перед новой | Добавить сброс значения |
Ручное удаление файлов из /var/lib/docker | Метаданные рассогласовались с файлами на диске | Не делать этого; использовать docker system prune — см. раздел 13 |
Поиск логов приложения через journalctl -u docker | Это логи daemon, а не containers | Использовать docker logs <container> |
Контрольные вопросы
На понимание:
- Почему
docker versionпоказывает две версии? - Что такое socket activation и как оно влияет на остановку Docker?
- Что произойдёт с работающими containers при
systemctl restart dockerс включённым и с выключеннымlive-restore? - Почему нельзя редактировать
/lib/systemd/system/docker.serviceнапрямую? - Почему ошибка в
daemon.jsonприводит к полной неработоспособности Docker, а не игнорируется?
На применение:
- Как посмотреть только ошибки daemon за последние 30 минут?
- Как проверить корректность
daemon.jsonдо перезапуска службы? - Как узнать фактическую строку запуска
dockerdсо всеми аргументами?
На диагностику:
systemctl status dockerпоказываетactivating (auto-restart), и состояние повторяется. Какова последовательность действий?- После добавления
"hosts": ["unix:///var/run/docker.sock"]вdaemon.jsondaemon перестал стартовать. В чём причина?
Краткое резюме
- CLI и daemon — разные программы; CLI только отправляет запросы через Unix socket.
- Установка создаёт два unit:
docker.serviceиdocker.socket. - Socket activation запускает daemon при первом обращении, поэтому остановки только
docker.serviceнедостаточно. - Логи daemon читаются через
journalctl -u docker.service; логи приложений — черезdocker logs. - Конфигурация daemon задаётся в
/etc/docker/daemon.json; файл по умолчанию отсутствует. - Синтаксическая ошибка в
daemon.jsonне даёт daemon запуститься — проверяйте до перезапуска. - Параметр задаётся либо в
daemon.json, либо в аргументахExecStart, но не в обоих местах. - Аргументы запуска изменяются через
systemctl edit, а не правкой unit-файла пакета. live-restoreпозволяет containers пережить перезапуск daemon.- Содержимое
/var/lib/dockerне редактируется вручную; для анализа используйтеdocker system df.
Официальные источники
| Источник | Ссылка | Что подтверждает |
|---|---|---|
| Docker daemon configuration | https://docs.docker.com/engine/daemon/ | Файл daemon.json, применение настроек, валидация |
| Configure the daemon with systemd | https://docs.docker.com/engine/daemon/proxy/ | Использование drop-in файлов systemd |
| dockerd CLI reference | https://docs.docker.com/reference/cli/dockerd/ | Все параметры daemon, флаг --validate, live-restore |
| Start containers automatically | https://docs.docker.com/engine/containers/start-containers-automatically/ | Взаимодействие restart policies и перезапуска daemon |
systemctl(1) man page | https://man7.org/linux/man-pages/man1/systemctl.1.html | Команды управления unit, edit, revert, cat |
journalctl(1) man page | https://man7.org/linux/man-pages/man1/journalctl.1.html | Флаги фильтрации журнала |
Навигация
← Предыдущий материал
Вернуться к разделу
Следующий материал → Первый container
Главное оглавление