Я экспериментировал с docker и docker-compose и у меня возник вопрос.
В настоящее время мой docker-compose.yml выглядит так:
app:
image: myname/php-app
volumes:
- /var/www
environment:
<SYMFONY_ENVIRONMENT>: dev
web:
image: myname/nginx
ports:
- 80
links:
- app
volumes_from:
- app
Приложение содержит php-fpm на порту 9000 и мой код приложения. Веб — это nginx с несколькими битами конфигурации.
Это работает так, как я и ожидал, однако для подключения nginx к php-fpm у меня есть эта строка:
fastcgi_pass app:9000;
Как мне эффективно масштабировать это? Если бы я хотел, например, чтобы был запущен один контейнер nginx и три контейнера приложений, то у меня наверняка будут три экземпляра php-fpm, которые попытаются прослушивать порт 9000.
Как мне разместить каждый экземпляр php-fpm на отдельном порту, но при этом знать, где они находятся в моей конфигурации nginx в любой момент времени?
Может быть, я выбрал неправильный подход?
Спасибо!
решение1
Одним из решений является добавление дополнительных экземпляров php-fpm в ваш файл docker-compose, а затем использование nginx upstream, как упоминалось в других ответах, для балансировки нагрузки между ними. Это сделано в этом примере репозитория docker-compose:https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137
upstream php {
#If there's no directive here, then use round_robin.
#least_conn;
server dockernginxphpfpm_php1_1:9000;
server dockernginxphpfpm_php2_1:9000;
server dockernginxphpfpm_php3_1:9000;
}
Это не совсем идеальный вариант, поскольку для масштабирования потребуется изменить конфигурацию nginx и docker-compose.yml.
Обратите внимание, что порт 9000 является внутренним для контейнера, а не для вашего фактического хоста, поэтому не имеет значения, есть ли у вас несколько контейнеров php-fpm на порту 9000.
Docker приобрел Tutum этой осенью. У них есть решение, которое объединяет контейнер HAProxy с их API для автоматической настройки конфигурации балансировщика нагрузки для работающих контейнеров, которые он балансирует. Это хорошее решение. Затем nginx указывает на имя хоста, назначенное балансировщику нагрузки. Возможно, Docker будет и дальше интегрировать этот тип решения в свои инструменты после приобретения Tutum. Статья об этом есть здесь:https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-балансировка-нагрузки-веб-сервиса
Tutum в настоящее время является платным сервисом. Rancher — проект с открытым исходным кодом, который предоставляет похожую функцию балансировки нагрузки. У них также есть "rancher-compose.yml", который может определять балансировку нагрузки и масштабирование настройки сервисов в docker-compose.yml. http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer
ОБНОВЛЕНИЕ 2017/03/06: Я использовал проект под названиемблокировкакоторый работает с Docker для автоматического обновления конфигурации nginx и перезапуска его. Также см. @iwaseatenbyagrue'sотвечатькоторый имеет дополнительные подходы.
решение2
Хотя этот пост датируется 2015 годом и я чувствую, что занимаюсь некропостингом (извините, сообщество), я считаю, что сейчас будет полезно добавить:
В настоящее время (и с тех пор, как был упомянут Kubernetes), когда вы работаете с Docker, вы можете использовать Kubernetes или Docker Swarm очень легко для решения этой проблемы. Оба оркестратора будут принимать ваши узлы docker (один узел = один сервер с Docker на нем), и вы можете развернуть на них службы, и они будут управлять вызовами портов для вас, используя оверлейные сети.
Поскольку я более сведущ в Docker Swarm, вот как можно подойти к решению этой проблемы (предполагая, что у вас есть один узел Docker):
Инициализируем рой:
docker swarm init
cd в корень вашего проекта
cd some/project/root
создайте стек Swarm из вашего docker-compose.yml (вместо использования docker-compose):
docker stack deploy -c docker-compose.yml myApp
Это создаст стек сервисов docker swarm с именем "myApp" и будет управлять портами для вас. Это означает: вам нужно добавить только одно определение "port: 9000:9000" в ваш сервис php-fpm в вашем файле docker-compose, а затем вы можете масштабировать сервис php-fpm, скажем, до 3 экземпляров, в то время как swarm автоматически магическим образом распределит нагрузку запросов между тремя экземплярами без необходимости какой-либо дополнительной работы.
решение3
Вы можете использовать апстрим для определения нескольких бэкэндов, как описано здесь:
https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx
Вам также захочется обновлять конфигурацию всякий раз, когда новые бэкэнды умирают/вступают в эксплуатацию, например:
решение4
Другой подход может заключаться в рассмотрении чего-то вродеконсул-шаблон.
И, конечно, в какой-то момент,Кубернетесвозможно, необходимо упомянуть.
Однако вы можете рассмотреть подход, немного более приближенный к «кускам веревки и клейкой ленты», посмотрев, что может сделать для вас использование событий Docker (запустите docker events --since 0
для быстрого примера).
Было бы довольно просто создать скрипт, отслеживающий эти события (учитывая, что доступно несколько клиентских пакетов, в том числе для Python, Go и т. д.), вносящий поправки в файл конфигурации и перезагружающий nginx (т. е. использующий подход consul-template, но без необходимости в consul).
Однако вернемся к исходной предпосылке: если ваши контейнеры php-fpm запущены в собственной сети (т. е. не используют сеть другого контейнера, например, nginx), то вы можете прослушивать порт 9000 столько контейнеров, сколько захотите — поскольку у них есть IP-адреса для каждого контейнера, проблем с «конфликтом» портов не возникнет.
То, как вы это масштабируете, скорее всего, будет зависеть от вашей конечной цели/варианта использования, но вы можете рассмотреть возможность размещения HAproxy между узлами nginx и php-fpm. Это может позволить вам просто назначить диапазон (и, возможно, создать docker network
) для ваших серверов php-fpm (например, 172.18.0.0/24) и настроить HAproxy на попытку использования любого IP-адреса в этом диапазоне в качестве бэкэнда. Поскольку HAproxy имеет проверки работоспособности, он может быстро определить, какие адреса активны, и использовать их.
Видетьhttps://stackoverflow.com/questions/1358198/nginx-удаление-серверов-вышестоящего-потока-из-пуладля обсуждения того, как nginx и haproxy справляются с апстримами.
Если вы не использовали для этого выделенную сеть Docker, вымощьнеобходимо выполнить ручное управление IP-адресами для узлов php-fpm.