Як перевірити стан, логи та метадані контейнера?
Три команди покривають усю observability-історію для одного container: docker ps для високорівневого стану, docker logs для того, що друкував застосунок, docker inspect для решти. Плюс docker stats для live-ресурсів.
Теорія
TL;DR
docker ps -a= поточний стан, порти, image, ім'я (one-line summary).docker logs <name>= stdout + stderr container.-fдля follow live,--tail Nдля останніх N рядків,--since 10mдля time-обмежених.docker inspect <name>= повний JSON config container, стану, мереж, volume, mount, env. Використовуй--formatдля одного поля.docker stats= live CPU, пам'ять, мережа, block I/O.--no-streamдля одного snapshot.docker top <name>= дерево процесів всередині container.docker port <name>= які host-порти мапляться на container-порти.
docker ps — швидкий стан
$ docker ps -a --filter name=web
CONTAINER ID IMAGE STATUS PORTS NAMES
a3f9d2b8c1e4 nginx:1.27-alpine Up 5 minutes 0.0.0.0:8080->80/tcp webЧотири колонки відповідають на більшість запитань: чи running? який image? з якого часу? які порти?
docker logs — що сказав застосунок
Daemon ловить stdout і stderr з PID 1 всередині container. docker logs їх назад читає.
docker logs web # усі логи з старту (може бути великим)
docker logs -f web # follow live (як tail -f)
docker logs --tail 100 web # останні 100 рядків
docker logs --since 10m web # останні 10 хвилин
docker logs --since 2026-04-30T10:00:00 web # з timestamp
docker logs -t web # prepend timestampsВажливо: логи приходять зі stdout/stderr PID 1. Якщо твій застосунок пише у файл всередині container, docker logs його не покаже. Налаштуй застосунок логувати у stdout, щоб це працювало, це 12-factor норма.
docker inspect — все інше
Повний JSON-dump стану і config container. Без --format це 200-рядковий JSON. З --format отримуєш рівно одне поле:
# Статус
docker inspect --format '{{.State.Status}}' web
# → running
# Exit code (після виходу container)
docker inspect --format '{{.State.ExitCode}}' web
# → 137
# OOM-killed?
docker inspect --format '{{.State.OOMKilled}}' web
# → true / false
# Restart count
docker inspect --format '{{.RestartCount}}' web
# → 3
# IP-адреса на дефолтному bridge
docker inspect --format '{{.NetworkSettings.IPAddress}}' web
# → 172.17.0.2
# Усі опубліковані порти
docker inspect --format '{{json .NetworkSettings.Ports}}' web
# → {"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}]}
# Mount'и
docker inspect --format '{{range .Mounts}}{{.Type}}: {{.Source}} -> {{.Destination}}\n{{end}}' webШаблон --format використовує Go text/template. Вивід docker inspect <name> (без format) показує структуру полів, які можна таргетувати.
docker stats — live ресурси
$ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a3f9d2b8c1e4 web 0.01% 12.5MiB / 7.8GiB 0.16% 2.1kB / 832B 0B / 0B 5
b7e1f4d6a2b8 db 2.34% 145MiB / 7.8GiB 1.82% 18.4kB / 12.7kB 4.1MB / 0B 9Без --no-stream оновлюється live як top. Корисно для виявлення memory leak (стабільне зростання MEM USAGE) або noisy neighbor.
docker top — дерево процесів всередині
$ docker top web
UID PID COMMAND
root 84231 nginx: master process nginx -g daemon off;
nginx 84290 nginx: worker processHost-side view: PID це host-PID, не container PID 1. Корисно для зіставлення ps aux | grep на host з тим, що всередині.
docker port — port mapping
$ docker port web
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080Швидкий спосіб побачити, що відкрито, без парсингу inspect.
Типові помилки
Шукати логи у writable-шарі
# НЕПРАВИЛЬНО: застосунок логує у /var/log/myapp.log всередині container
$ docker exec web cat /var/log/myapp.log
# ПРАВИЛЬНО: налаштувати застосунок логувати у stdout, тоді
$ docker logs webЗастосунки, що логують у файли всередині container, не з'являються у docker logs. Вони ще й втрачаються при docker rm. Завжди логуй у stdout/stderr для контейнеризованих застосунків.
Забути --no-stream у скриптах
# Висить вічно у скрипті (чекає live-апдейтів)
$ docker stats > stats.txt
# Snapshot, вихід, повернення
$ docker stats --no-stream > stats.txtdocker stats за замовчуванням стрімить. У CI або скрипті завжди додавай --no-stream.
docker inspect без --format у скриптах
# Громіздко, важко парсити
$ docker inspect web | grep IPAddress | head -1 | awk -F'"' '{print $4}'
# Чисто
$ docker inspect --format '{{.NetworkSettings.IPAddress}}' webФлаг --format саме для пропуску grep/awk-танцю.
Читати старі логи без --tail
Довгоживучий container може мати гігабайти логів. docker logs <name> (без флагів) намагається вивалити їх усі. Використовуй --tail 1000 або --since для обмеження.
Реальне застосування
- «Чи up сервіс X?» →
docker ps --filter name=X --filter status=running -q. Порожній вивід = не запущений. - «Чому build-container вийшов?» →
docker logs --tail 200 build-container. - «На якій IP база?» →
docker inspect --format '{{.NetworkSettings.Networks.bridge.IPAddress}}' db. - «Скільки пам'яті web використовує зараз?» →
docker stats --no-stream web. - «Це OOM крашнув?» →
docker inspect --format '{{.State.OOMKilled}}' container.
Питання для поглиблення
Q: Чим docker logs відрізняється від docker logs -f?
A: Без -f вивалює накопичені логи і виходить. З -f (follow) стрімить нові, як tail -f. Ctrl+C, щоб зупинити.
Q: Чи можу побачити логи до того, як container рестартував?
A: Так, docker logs тримає логи через рестарти (до docker rm). Дефолтний driver (json-file) дописує у log-файл на диску, що переживає рестарт. Інші драйвери (syslog, journald, fluentd) шиппять логи зовні, у такому випадку docker logs може не працювати, перевір docker inspect --format '{{.HostConfig.LogConfig.Type}}'.
Q: Яка різниця між docker inspect і docker container inspect?
A: docker inspect загальний, працює на container, image, volume, network. docker container inspect явна форма лише для container. Однаковий вивід для container.
Q: Як побачити ліміти ресурсів, застосовані до container?
A: docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.NanoCpus}}' <name>. Пам'ять у байтах, CPU у nanoCPU (1 CPU = 1e9). Або docker stats показує use vs limit live.
Q: (Senior) Як дебажити container, що рестартується надто швидко, щоб приєднатися?
A: Кілька опцій. (1) Перевіряй docker logs --tail 200 між рестартами, навіть короткі сплески виводу зберігаються. (2) Override entrypoint sleep'ом, щоб лишався up: docker run --entrypoint sleep myimg 3600, тоді docker exec всередину. (3) Додай --restart=no, щоб крашнувся раз і лишився exited; тоді docker logs і docker inspect дають стабільний snapshot. (4) Запускай зламаний image з реальною entrypoint-командою, перенесеною у debug-shell wrapper.
Приклади
Швидкий health-check loop
$ for c in web api db; do
s=$(docker inspect --format '{{.State.Status}}' "$c" 2>/dev/null || echo missing)
h=$(docker inspect --format '{{.State.Health.Status}}' "$c" 2>/dev/null || echo "-")
echo "$c: $s ($h)"
done
web: running (healthy)
api: running (healthy)
db: running (starting)Стан плюс health-статус для кількох container одразу. Чудово для shell-скриптів.
Tail логи з кількох сервісів у Compose
$ docker compose logs -f --tail 50
# Стрім з усіх сервісів, кольоровано по імені.
$ docker compose logs -f --tail 50 api db
# Тільки api і db.Compose ставить гарний multi-service tail поверх звичайного docker logs.
Перевірити, чому останній exited container помер
$ docker inspect --format '{{.State.Status}} ({{.State.ExitCode}}) OOM={{.State.OOMKilled}} Err={{.State.Error}}' \
$(docker ps -alq)
exited (137) OOM=true Err=
# → exited з 137 (SIGKILL); OOMKilled=true → досягнуто memory-ліміту.Чотири поля разом зазвичай вказують на причину без відкриття JSON-dump.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.
Коментарі
Ще немає коментарів