Урок 8 из 8 · 20 мин · обновлено

Отладка, уборка и хорошие привычки

Что делать, если контейнер не запускается или сразу завершается: логи, коды выхода, docker exec и inspect. Частые ошибки и их причины, как освободить место на диске, хорошие привычки работы с Docker и что изучать дальше.

Если что-то пошло не так

Контейнер не запускается, сразу завершается или работает не так, как ждали. Порядок действий почти всегда один.

1. Посмотрите статус и код выхода:

Терминал
docker ps -a
Результат
NAMES   IMAGE         STATUS
db      postgres:16   Exited (1) 5 seconds ago

Exited (0) — программа завершилась сама, без ошибки: так ведёт себя hello-world. Любое другое число — завершилась с ошибкой.

2. Прочитайте логи:

Терминал
docker logs db
docker logs --tail 20 db   # только последние 20 строк

В примере выше база сообщит, что не задан пароль: контейнер запустили без -e POSTGRES_PASSWORD. Логи отвечают на большинство вопросов.

3. Посмотрите настройки контейнера:

Терминал
docker inspect db

Команда выводит всё о контейнере в формате JSON: образ, переменные окружения, тома, порты, сеть. Длинно, но удобно, когда нужно убедиться, что том подключился куда нужно, а переменная действительно передана.

Заглянуть в работающий контейнер

docker exec выполняет команду внутри уже работающего контейнера. Открыть в нём командную строку:

Терминал
docker exec -it web sh

Внутри можно посмотреть файлы, проверить настройки, а потом выйти командой exit. В отличие от docker run --rm -it, контейнер после выхода продолжит работать.

Теперь понятна команда из урока 5:

Терминал
docker exec -it db psql -U postgres -c "SELECT * FROM notes;"

Внутри контейнера db запустить клиент psql от пользователя postgres и выполнить запрос из -c. Без -c откроется интерактивный psql, выход из него — \q.

Как потребляют ресурсы работающие контейнеры, покажет docker stats: процессор, память и сеть в реальном времени. Выход — Ctrl + C.

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

Сообщение Что значит и что делать
port is already allocated порт занят другим контейнером или программой: выберите другой или остановите занявший
Conflict. The container name "/web" is already in use контейнер с таким именем уже есть: удалите его или дайте новому другое имя
pull access denied или manifest unknown опечатка в имени образа или такого тега нет: проверьте на Docker Hub
Cannot connect to the Docker daemon Docker не запущен: откройте Docker Desktop или запустите службу на Linux
no space left on device закончилось место: почистите неиспользуемое, см. ниже

Уборка: где кончилось место

Образы, остановленные контейнеры и тома незаметно занимают гигабайты. Посмотреть, сколько:

Терминал
docker system df

Убрать неиспользуемое — остановленные контейнеры, неиспользуемые сети, образы без тега и кэш сборки:

Терминал
docker system prune

Команда спросит подтверждение и не тронет работающие контейнеры, образы с тегами и тома. Флаги делают её мощнее и опаснее: -a удалит все образы, по которым не создан ни один контейнер, а --volumes — неподключённые тома без имени вместе с данными. Перед ними проверьте, что ничего нужного не потеряется.

Убрать за курсом:

Терминал
docker compose down -v      # в папке my-site
docker volume rm pgdata     # том из уроков 5–6
docker system prune

Хорошие привычки

  • Фиксируйте версии: postgres:16, а не postgres. Поведение не изменится внезапно.
  • Начинайте с официальных образов и лёгких вариантов вроде alpine.
  • Не кладите пароли и ключи в образ: всё, что попало в образ, может прочитать любой, кто его скачал. Секреты передают через переменные окружения или .env.
  • Держите .dockerignore рядом с Dockerfile.
  • Один процесс — один контейнер: база отдельно, сайт отдельно. Так их проще обновлять и перезапускать.
  • Данные — в томах: всё, что записано внутри контейнера, исчезнет вместе с ним.
  • Описывайте проект в compose.yaml, а не в памяти и заметках.

Что дальше

Вы умеете запускать готовые программы, собирать свои образы, хранить данные и поднимать стенд из нескольких контейнеров. Этого хватает для повседневной работы разработчика и тестировщика. Следующие темы, если Docker понравился:

  • многоэтапная сборка — как делать маленькие образы для продакшена;
  • CI/CD — автоматическая сборка образов и запуск тестов при каждом изменении кода;
  • Kubernetes — запуск сотен контейнеров на многих серверах. Это уже профессия DevOps-инженера.

Все команды курса собраны в шпаргалке — сохраните её в закладки.

Попробуйте сами. Запустите PostgreSQL без пароля: docker run -d --name broken postgres:16. Выясните по логам, почему контейнер остановился, исправьте запуск и откройте командную строку внутри работающей базы. Затем уберите за собой.

Решение
Терминал
docker run -d --name broken postgres:16
docker ps -a          # статус Exited (1)
docker logs broken    # база просит задать POSTGRES_PASSWORD
docker rm broken
docker run -d --name fixed -e POSTGRES_PASSWORD=secret postgres:16
docker exec -it fixed sh

Внутри контейнера выполните psql -U postgres, затем \q и exit. Уборка:

Терминал
docker rm -f fixed

У контейнера fixed нет тома с именем, поэтому Docker создал для данных анонимный том — у него вместо имени длинный ID. Такие тома убирает docker volume prune.

Мини-тест: проверьте себя

Закрепите урок: несколько вопросов, разбор ответов — в конце.

  1. Контейнер запустился и сразу остановился. С чего начать?

  2. Чем docker exec отличается от docker run?

  3. Что опасного в команде docker system prune -a --volumes?