При проектировании информационной системы очень важна ясность. Нет ничего лучше, чем элегантно построенное приложение, в котором нет лишних деталей, в том числе — лишних связей между компонентами.
К счастью, Docker позволяет изолировать процессы друг от друга и организовывать связь между ними посредством заранее указанных портов и общих директорий. В большинстве случаев, для успеха мероприятия необходима только однонаправленная связь контейнеров, например: веб-сервер использует php-fpm, либо php-fpm использует базу данных. В этом простом случае, никаких проблем не возникает, установить такую связь между несколькими контейнерами, используя Docker Compose, очень просто:
# ~/docker-apps/testapp/test.yml
fpm:
build: ./build/fpm
nginx:
build: ./build/nginx
links:
- fpm
Запускаем. Как видно, всё работает:
docker-compose -f test.yml up -d
Creating testapp_fpm_1...
Creating testapp_nginx_1...
docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------
testapp_fpm_1 /usr/sbin/php5-fpm -F Up 9000/tcp
testapp_nginx_1 /usr/sbin/nginx Up 80/tcp
Из контейнера testapp_nginx_1 можно адресовать testapp_fpm_1 посредством прописанных самим Docker хостов. Посмотрим на /etc/hosts:
docker exec testapp_nginx_1 cat /etc/hosts
...
172.17.0.5 testapp_fpm_1 2bae5bf71e09
172.17.0.5 fpm 2bae5bf71e09 testapp_fpm_1
172.17.0.5 fpm_1 2bae5bf71e09 testapp_fpm_1
В принципе, возможна ситуация, когда оба связанных процесса должны знать друг о друге. Например, если поднят Selenium: необходимо из него иметь доступ до веб-сервера, чтобы исполнять тестовые задания; но также от веб-сервера нужен доступ до самого Selenium, чтобы запускать эти задания посредством BDD-фреймворка. Для ясности примера относительно предыдущего, допустим, что нам нужен доступ из nginx в php-fpm и наоборот.
# ~/docker-apps/testapp/test2.yml
fpm:
build: ./build/fpm
links:
- nginx
nginx:
build: ./build/nginx
links:
- fpm
Запускаем?
docker-compose -f test2.yml up -d
Circular import between fpm and nginx
К счастью, решение есть. Невозможно добавить перекрестные ссылки только на этапе старта, добавить их после старта — никто запретить не может. На помощь придет ambassador — образ процесса-прокси, единственная задача которого — создание перекрестных ссылок между контейнерами.
# ~/docker-apps/testapp/test3.yml
fpm:
build: ./build/fpm
links:
- ambassador:nginx
nginx:
build: ./build/nginx
links:
- ambassador:fpm
ambassador:
image: cpuguy83/docker-grand-ambassador
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
command: '-name testapp_fpm_1 -name testapp_nginx_1'
Запускаем:
docker-compose -f test3.yml up -d
Creating testapp_ambassador_1...
Creating testapp_nginx_1...
Creating testapp_fpm_1...
Что произошло?
docker exec astgo_nginx_1 cat /etc/hosts
...
172.17.0.11 ambassador_1 f3437e869aff testapp_ambassador_1
172.17.0.11 testapp_ambassador_1 f3437e869aff
172.17.0.11 fpm f3437e869aff testapp_ambassador_1
Как видно, Docker добавил стандартные записи для ambassador, а уже ambassador добавил запись, указывающую на контейнер fpm. Стоит заметить, не напрямую — а через тот же самый ambassador.