Запуск команды без запуска связанных сервисов
На этом шаге мы научимся запускать команды в Docker-контейнере, который является частью многоконтейнерного приложения, без запуска других связанных сервисов. Это особенно полезно для выполнения миграций базы данных, setup-скриптов или отладочных команд в одном сервисе без необходимости поднимать весь стек приложения.
Хотя Docker Compose является стандартным инструментом для управления многоконтейнерными приложениями и имеет функции для выполнения одноразовых команд в конкретных сервисах, здесь мы продемонстрируем базовые концепции Docker. Поскольку Docker Compose не предустановлен в этой среде, мы сосредоточимся на использовании команды docker run
с сетевыми настройками.
Смоделируем простой сценарий с двумя контейнерами: веб-приложением и базой данных. Будем использовать образ ubuntu
для представления нашего веб-приложения и образ postgres
для базы данных.
Сначала загрузим образ postgres
:
docker pull postgres:latest
Вы увидите вывод, указывающий на загрузку образа:
Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Теперь создадим Docker-сеть, чтобы наши контейнеры могли взаимодействовать друг с другом по именам.
docker network create my-app-network
Вы увидите идентификатор созданной сети:
<network_id>
Запустим контейнер postgres
и подключим его к нашей сети. Также установим пароль для пользователя PostgreSQL.
docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres
Вы увидите идентификатор контейнера, указывающий, что контейнер с базой данных запущен в фоне:
<container_id>
Представим, что нашему контейнеру "веб-приложения" нужно выполнить команду, взаимодействующую с базой данных, например, скрипт миграции. При использовании Docker Compose мы могли бы выполнить команду в веб-сервисе, и Docker Compose автоматически настроил бы сеть и связи.
Используя только docker run
, если мы запустим контейнер веб-приложения, которому нужно подключиться к my-database
, он должен находиться в той же сети.
Выполним команду в контейнере ubuntu
, подключенном к той же сети, имитируя команду, которая может взаимодействовать с базой данных. Просто попробуем пропинговать контейнер базы данных по его имени (my-database
).
docker run --network my-app-network ubuntu ping -c 4 my-database
Эта команда:
- Создаст новый контейнер из образа
ubuntu
- Подключит его к сети
my-app-network
- Выполнит команду
ping -c 4 my-database
внутри контейнера
Поскольку контейнер ubuntu
находится в той же сети, что и my-database
, он может разрешить имя my-database
в IP-адрес контейнера с базой данных и пропинговать его.
Вы увидите вывод с результатами ping-запросов:
PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms
--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms
Это демонстрирует, что можно выполнить одноразовую команду в контейнере и обеспечить её взаимодействие с другими контейнерами в той же сети, без необходимости запускать стандартный сервис контейнера (в данном случае контейнер ubuntu
не имеет типичного "сервиса"). Ключевой момент — подключение контейнера с выполняемой командой к той же сети, где находятся сервисы, с которыми нужно взаимодействовать.
Наконец, очистим запущенный контейнер базы данных и сеть.
docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network