В данный момент мы часто имеем ситуацию, когда каждый отдельный проект имеет настройки docker контейнеров, что производятся через конфигурационный файл docker compose. Пока обращение контейнеров друг к другу происходит в рамках одного такого файла конфигурации, все понятно. Но что, если мы имеем, скажем 2 или 3 подпроекта, которые должны общаться по сети (например по http)? Это могут быть, как вариант, микро сервисы. В данной статье будет показано как настроить такое взаимодействие.
Для имитации 2 разных проектов создадим 2 отдельных файла docker-compose.yml
version: '3.6'
services:
web:
image: nginx
hostname: project1
ports:
- "127.0.0.101:80:80"
networks:
some_network:
aliases:
- project1.local
- www.project1.local
networks:
some_network:
# Общая сеть со смежными проектами
name: 'our_network'
version: '3.6'
services:
web:
image: nginx
hostname: project2
ports:
- "127.0.0.102:80:80"
networks:
some_network:
aliases:
- project2.local
- www.project2.local
networks:
some_network:
# Общая сеть со смежными проектами
name: 'our_network'
В каждом проекте по 1 сервису (контейнеру) с именем web. В обоих случаях создаем контейнер на базе образа nginx. Прокидываем порт 80 на разные host IP. В этом случае в браузере будут доступны проекты по URL http://127.0.0.101 и http://127.0.0.102. Если у вас заняты эти IP (не запустится nginx в каком либо из проектов), то используйте другие IP вида 127.*.*.*
Теперь запустим окружение первого проекта в папке project1:
$ docker compose up -d
[+] Running 2/2
⠿ Network our_network Created 0.1s
⠿ Container project1-web-1 Started
Сейчас в браузере можно открыть страницу Welcome to nginx! по адресу http://127.0.0.101. А внутри самого контейрера можно обратиться и по доменному имени за счет заданого алиаса.
$ docker compose exec web curl project1.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
...
В то же время домен из второго проекта доступен не будет:
$ docker compose exec web curl project2.local
curl: (6) Could not resolve host: project2.local
Чтобы он стал доступен мы запустим окружение второго проекта в папке project2:
$ docker compose up -d
[+] Running 1/1
⠿ Container project2-web-1 Started
Теперь в папке первого проекта project1 можем увидеть доступность домена второго проекта из контейнера первого:
$ docker compose exec web curl project2.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
...
И в папке второго проекта project2 можем убедиться, что доступен домен первого проекта из контейнера второго:
$ docker compose exec web curl project1.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
...
Магия происходит за счет задания сети имени name: 'our_network'
. Эта возможность доступна, если вы используйте формат docker-compose.yml не ниже версии 3.5. Когда таким образом указывается имя сети, то к нему не добавляется префикс проекта. В итоге контейнер одного проекта видит сеть под тем же именем, что и другой проект. Можно убедиться в наличии сети с таким именем при помощи команды docker network ls
:
$ docker network ls | grep our
3448ab685c12 our_network bridge local
Если бы такой сети мы не создали, то запуск первого проекта привел бы к созданию сети по умолчанию project1_default, а второго – project2_default.
Мы могли бы создать сеть без docker-compose.yml, через команду docker:
$ docker network create -d bridge our_network2
ddfd35c35b68d034950f415e06fc4074b62eedf23e6680508181f773740d43e5
$ docker network ls | grep our
f292f72ce35d our_network bridge local
ddfd35c35b68 our_network2 bridge local
Тогда в описании сети нужно было бы указать параметр external
. Однако, удобнее, чтобы сеть создавалась автоматически при запуске любого из проектов.
Важный момент. Если контейнерам явно указана сеть (как в примерах выше), то скорее всего, для таких контейнеров не будет доступна сеть default. Что приведет к проблемам обращения к ним из контейнеров сети default. Чтобы избежать таких проблем, нужно в списке сетей контейнера с явно указанной сетью также указывать и сеть default:
## Располагается в секции контейнера
networks:
default: # Здесь указан сеть default
some_network:
aliases:
- project2.local
- www.project2.local
Код примеров доступен в репозитории https://github.com/itelmenko/myblog/tree/main/examples/docker-network
Полезные ссылки
- https://docs.docker.com/compose/networking/#specify-custom-networks
- https://docs.docker.com/compose/compose-file/compose-file-v2/#network-configuration-reference
Очень помогло, спасибо
Спасибо
Сделал отдельный контейнер с PostgreSQL 14. Развернул из docker-compose
Отдельным docker-compose развернул php и nginx
Сети у всех с одинаковым названием.
Через DBever коннект к БД есть
А вот из php доступа нет.
В итоге помогло
networks:
laravel:
driver: bridge
external: true
name: laravel
Теперь у меня один контейнер с PGSQL14 для кучи проектов. Удобнее чем под каждый проект поднимать свой контейнер с БД
Aleksandr, спасибо за комментарий. Кому-то еще поможет.