Добавить в корзинуПозвонить
Найти в Дзене
Анастасия Софт

Первые шаги с Docker CLI: Жизненный цикл контейнера. Урок 2 Docker.

Любой контейнер имеет свой жизненный цикл. Он не существует вечно: он создается из образа, выполняет свою задачу (крутится в фоне или завершает расчеты), останавливается и, в конечном итоге, удаляется. Ваша задача как инженера — уметь управлять этим циклом. Прежде чем запустить контейнер, нам нужен чертеж — образ (Image). Официальный глобальный реестр образов называется Docker Hub. Там лежат готовые и настроенные образы для баз данных (PostgreSQL, MySQL), веб-серверов (Nginx, Apache), языковых сред (Java, Python, Node.js) и тысяч других программ. Чтобы скачать образ на свой компьютер без его запуска, используется команда:
docker pull postgres:15 Команда docker run — это швейцарский нож Docker. Она делает три вещи одновременно: Давайте разберем запуск базы данных, которая часто нужна при разработке backend-приложений. docker run --name my-database -e POSTGRES_PASSWORD=secret_pass -p 5432:5432 -d postgres:15 Выглядит страшно? Давайте разберем по косточкам (флагам): Мы даем нашему контейн
Оглавление
Первые шаги с Docker CLI: Жизненный цикл контейнера. Урок 2 Docker.
Первые шаги с Docker CLI: Жизненный цикл контейнера. Урок 2 Docker.

Любой контейнер имеет свой жизненный цикл. Он не существует вечно: он создается из образа, выполняет свою задачу (крутится в фоне или завершает расчеты), останавливается и, в конечном итоге, удаляется. Ваша задача как инженера — уметь управлять этим циклом.

1. Откуда берутся образы? (Docker Hub и docker pull)

Прежде чем запустить контейнер, нам нужен чертеж — образ (Image).

Официальный глобальный реестр образов называется Docker Hub. Там лежат готовые и настроенные образы для баз данных (PostgreSQL, MySQL), веб-серверов (Nginx, Apache), языковых сред (Java, Python, Node.js) и тысяч других программ.

Чтобы скачать образ на свой компьютер без его запуска, используется команда:
docker pull postgres:15

  • Где postgres — имя образа, а 15 — это тег (tag), указывающий конкретную версию. Если не указать тег, Docker скачает версию latest (последнюю), что в реальных проектах делать не рекомендуется во избежание неожиданных обновлений.

2. Главная команда: docker run

Команда docker run — это швейцарский нож Docker. Она делает три вещи одновременно:

  1. Ищет образ локально (если нет — делает pull из Docker Hub).
  2. Создает из него новый контейнер.
  3. Запускает этот контейнер.

Давайте разберем запуск базы данных, которая часто нужна при разработке backend-приложений.

docker run --name my-database -e POSTGRES_PASSWORD=secret_pass -p 5432:5432 -d postgres:15

Выглядит страшно? Давайте разберем по косточкам (флагам):

  • --name my-database

Мы даем нашему контейнеру понятное имя. Если этого не сделать, Docker сгенерирует случайное забавное имя (например, crazy_turing).

  • -e POSTGRES_PASSWORD=secret_pass

Флаг -e передает переменные окружения (Environment variables) внутрь контейнера. Официальный образ Postgres требует задать пароль для базы данных, иначе он откажется запускаться.

  • -p 5432:5432

Проброс портов (Port mapping). Левая часть — порт на вашем локальном компьютере, правая — порт внутри контейнера. Мы говорим: «Всё, что приходит на порт 5432 моего ноутбука, отправляй на порт 5432 внутрь контейнера».

  • -d (detach)

Запуск в фоновом режиме. Если не указать этот флаг, логи базы данных займут ваш терминал, и вы не сможете вводить новые команды (пока не нажмете Ctrl+C, что убьет контейнер).

  • postgres:15

Указание образа, из которого создается контейнер (всегда ставится в конце).

3. Мониторинг: Кто здесь работает?

Контейнер запущен в фоне. Как убедиться, что всё хорошо?

  • docker ps — показывает список только активных (запущенных) контейнеров. Вы увидите ID контейнера, имя, статус и проброшенные порты.
  • docker ps -a (флаг -a означает all) — показывает вообще все контейнеры, включая те, что были остановлены или упали с ошибкой.
  • docker logs my-database — выводит логи контейнера. Это главный инструмент отладки! Если ваше приложение не может подключиться к БД или контейнер упал, логи покажут почему. Можно добавить флаг -f (docker logs -f my-database), чтобы читать логи в реальном времени.

4. Остановка, запуск и уборка мусора

Контейнеры — это временные сущности. Если вы закончили работу над проектом на сегодня, вы можете остановить контейнер, чтобы не тратить оперативную память компьютера:

  • docker stop my-database: Мягко останавливает контейнер (посылает сигнал завершения процессу).
  • docker start my-database: Снова запускает ранее остановленный контейнер. Данные внутри него сохранятся (если только вы его не удалите).
  • docker restart my-database: Удобно, если вы поменяли какие-то внешние настройки и нужно перезагрузить сервис.

Когда контейнер вам больше не нужен совсем, его нужно удалить.

  • docker rm my-database: Удаляет контейнер (он должен быть предварительно остановлен). Чтобы удалить работающий контейнер принудительно, используйте docker rm -f my-database.

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

  • docker rmi postgres:15 (rmi = remove image).

Блок самопроверки

Внимательно прочитайте задачу и попробуйте решить типичную проблему разработчика.

Ситуация: Вы разрабатываете новое Java-приложение. Для локального тестирования вам понадобилось поднять веб-сервер Nginx. Вы вводите команду:

docker run -d --name test-server -p 8080:80 nginx

Однако вместо ID успешно запущенного контейнера Docker выдает вам ошибку:
Error response from daemon: driver failed programming external connectivity on endpoint test-server: Bind for 0.0.0.0:8080 failed: port is already allocated.

Ваше Java-приложение, запущенное прямо на вашем ноутбуке в IDE (например, IntelliJ IDEA), сейчас тоже работает и обрабатывает запросы.

Вопросы:

  1. Что именно означает эта ошибка?
  2. Как с помощью одной команды Docker посмотреть, не занят ли этот ресурс другим контейнером (на случай, если проблема не в вашей IDE)?
  3. Как изменить исходную команду запуска Nginx, чтобы контейнер успешно стартовал, не мешая вашему Java-приложению, которое уже работает на ноутбуке?
Подумайте над ответами и зафиксируйте их, прежде чем смотреть разбор.
😎

Ответ и разбор построчно

Краткие ответы:

  1. Ошибка означает конфликт портов (порт 8080 на хосте уже занят).
  2. Команда docker ps.
  3. Изменить левую часть в флаге -p, например: docker run -d --name test-server -p 8081:80 nginx.

Построчный разбор логики:

  1. «Что именно означает эта ошибка?»
    Разбор: Конструкция Bind for 0.0.0.0:8080 failed: port is already allocated — это самая частая ошибка новичков. Флаг -p 8080:80 приказывает Docker "захватить" порт 8080 на вашей физической машине (хосте) и направить его в порт 80 контейнера. Но порт 8080 уже занят запущенным Java-приложением в вашей IDE. Два разных процесса на одном компьютере не могут слушать один и тот же внешний порт одновременно.
  2. «Как с помощью одной команды посмотреть, не занят ли ресурс другим контейнером?»
    Разбор: Команда docker ps покажет все запущенные контейнеры. Если вы забыли, что час назад уже запустили другой контейнер (например, панель управления или другой сервис) с пробросом на порт 8080, вы увидите это в столбце PORTS вывода этой команды (там будет строка вроде 0.0.0.0:8080->80/tcp).
  3. «Как изменить команду, чтобы запустить Nginx, не мешая Java-приложению?»
    Разбор: Порт внутри контейнера Nginx по умолчанию всегда 80 — это трогать не нужно (он изолирован). Изменить нужно порт на вашей хост-машине (левая часть до двоеточия). Вы можете выбрать любой свободный порт, например 8081 или 9000.
    Правильная команда:
    docker run -d --name test-server -p 8081:80 nginx.
    После этого вы сможете открыть в браузере localhost:8081 и увидеть стартовую страницу Nginx, в то время как ваше Java-приложение продолжит спокойно работать на localhost:8080.