Последнее время часто сталкиваюсь с задачами, когда нужно объединить несколько проектов, каждый со своим docker-compose.yml, в одну общую сеть. За частую это связанно с тем, что микро сервисы разрабатывают разные команды, но они должны обменивать между собой и базой информацией. При этом сами проекты, за частую не настолько объемные, что бы держать всё это дело в Kubernetes.
Первый раз при реализации — пришлось погуглить, но как оказалось — внятных статей на эту тему не описано. Потому решил написать свою.
В целом задача не сложная и реализовать её можно по разному, в т.ч. сильно зависит от версии docker-compose которую вы используете. В статье рассмотрю работу на примере docker-compose v3.5
Дано:
— Два проекта со своими docker-compose.yml:
— В первом СУБД Postgress и самописный сервис, который обращается к базе
— Во втором просто сервис, который так же должен обращаться к базе выше
В версии 3.5 появилась удобная фишка network name
При указании имени сети — docker, при развертывании, попробует добавить контейнер в сеть с этим именем, а если такой сети нет — создаст.
Это удобно в том числе, если порядок развертывания для вас не важен, например в случае когда сервисы друг от друга не зависят напрямую.
Пример первого docker-compose.yml
## Версия 3.5
version: "3.5"
services:
## Стандартный шаблон сервиса Postgres
postgres:
image: postgres:12
command: postgres -c 'max_connections=400'
volumes:
- /srv/services/postgres/data:/var/lib/postgresql/data
expose:
- "5432"
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=****
- POSTGRES_USER=postgres
- POSTGRES_DB=database_name
## Указываем алиас по которому контейнер будет виден в общей сети
networks:
- postgress
## Описываем сферического коня в вакууме (самописный сервис)
service_1:
image: service1_img:latest
ports:
- 1961:1961
- 8444:8444
## Конкретно он пусть зависит от запуска базы
depends_on:
- postgres
## Передаем параметры подключения к базе
environment:
- DB_URL=jdbc:postgresql://postgres:5432/database_name
- DB_LOGIN=postgres
- DB_PASSWORD=****
## Указываем алиас по которому контейнер будет виден в общей сети
networks:
- service_1
## Описываем сети, каждому алиасу присваиваем одно имя сети
networks:
postgress:
name: network_name
service_1:
name: network_name
А теперь опишем docker-compose.yml для второго сервиса, который так же должен попадать в сеть с именем network_name
## Версия 3.5
version: "3.5"
services:
## Описываем второй сервис
service_2:
image: service2_img:latest
volumes:
- /some/volume:/mount/somewhere
ports:
- 1962:1962
## Передаем параметры подключения к базе, как у сервиса_1
environment:
- DB_URL=jdbc:postgresql://postgres:5432/database_name
- DB_LOGIN=postgres
- DB_PASSWORD=****
## Указываем алиас по которому контейнер будет виден в общей сети
networks:
- service_2
## Присваиваем имя сети, как в соседнем файле.
networks:
service_2:
name: network_name
На этом всё. Файлы можно запускать в разнобой с помощью docker-compose up -d
При запуске любого из них — будет создана сеть с именем «network_name», а второй подключиться в неё.
Дополнительно:
Если потребуется просто добавить контейнер в эту-же сетку, но без docker-compse — это можно выполнить с помощью команды:
docker run --network=network_name imagename:imageversion
Небольшая ремарка. Данная функция реализована в рамках одного хоста. Если вам требуется объединить контейнеры, которые крутятся на разных хостах — вам нужен docker swarm или kubernetes или любой другой аналогичный метод.
Полезные материалы по теме:
Официальная документация:
https://docs.docker.com/compose/compose-file/compose-file-v3/
примеров использования, хотя бы curl’ом, не хватает, а то сделал как указано здесь, а все равно не могу достучаться до соседнего контейнера
Спасибо за комментарий, доработаю этот момент в ближайшее время.
По вашей проблеме — проверьте что в имени контейнера нет запрещенных для http знаков, например «_», это не очевидно, но если контейнер называется app_1 то при выполнении http запроса по имени http://app_1 curl не будет достукиваться, даже не смотря на то что контейнер отвечает соседу по остальным протоколам.
Так же рекомендую проверить корректность написания yaml, и проверить доступность по имени другими средствами например icmp или telnet