私は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
アプリには、ポート9000のphp-fpmと私のアプリケーションコードが含まれています。 Webはnginxで、いくつかの構成が含まれています。
これは、私が期待するように機能しますが、nginxをphp-fpmに接続するには、次の行を使用します。
fastcgi_pass app:9000;
これを効果的にスケーリングするにはどうすればよいですか?たとえば、1つのnginxコンテナーを実行し、3つのアプリコンテナーを実行したい場合は、3つのphp-fpmインスタンスがすべてポート9000でリッスンしようとしていることを確認します。
どのようにして各php-fpmインスタンスを別のポートに置くことはできますが、それらがいつでも私のnginx構成のどこにあるかを知ることができますか?
私は間違ったアプローチを取っていますか?
ありがとう!
1つの解決策は、追加のphp-fpmインスタンスをdocker-composeファイルに追加し、他の回答で述べたようにnginxアップストリームを使用して、それらの間の負荷分散を行うことです。これは、この例の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 configとdocker-compose.ymlを変更する必要があるため、これは実際には理想的ではありません。
9000ポートはコンテナーの内部であり、実際のホストではないため、ポート9000に複数のphp-fpmコンテナーがあることは問題ではありません。
Dockerは今秋にTutumを買収しました。それらには、HAProxyコンテナーとAPIを組み合わせて、ロードバランサーの構成を、ロードバランシングを実行しているコンテナーに自動的に調整するソリューションがあります。それは素晴らしい解決策です。次に、nginxはロードバランサに割り当てられたホスト名を指します。おそらく、DockerはTutumの買収後に、このタイプのソリューションをツールにさらに統合するでしょう。それについての記事がここにあります: https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-load-balancing-a- web-service
Tutumは現在有料サービスです。 Rancherは、同様の負荷分散機能を提供するオープンソースプロジェクトです。また、Docker-compose.ymlでサービスセットアップの負荷分散とスケーリングを定義できる「rancher-compose.yml」もあります。 http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/http://docs.rancher.com/rancher/concepts /#load-balancer
UPDATE 2017/03/06:私は interlock と呼ばれるプロジェクトを使用しました。これはDockerと連携してnginx設定を自動的に更新し、再起動します。 @iwaseatenbyagrueの answer も参照してください。これには追加のアプローチがあります。
ここで説明するように、アップストリームを使用して複数のバックエンドを定義できます。
https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx
また、次のような新しいバックエンドが停止またはサービスに入るたびに、構成を更新する必要があります。
Nginxコンテナとphp-fpmコンテナが同じホスト上にある場合、ホスト上で小さな dnsmasq インスタンスを構成して、Nginxコンテナが使用し、スクリプトを実行してDNSを自動的に更新できます。コンテナのIPアドレスがいつ変更されたかを記録します。
これを行うために 小さなスクリプト を記述しました(以下に貼り付けます)。これにより、コンテナーの名前と同じ名前を持つDNSレコードが自動的に更新され、コンテナーのIPアドレスをポイントします。
#!/bin/bash
# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}
# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}
# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}
declare -A service_map
while true
do
changed=false
while read line
do
name=${line##* }
ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
then
service_map[$name]=$ip
# write to file
echo $name has a new IP Address $ip >&2
echo "Host-record=$name,$ip" > "${DNSMASQ_CONFIG}/docker-$name"
changed=true
fi
done < <(${DOCKER} ps | ${TAIL} -n +2)
# a change of IP address occured, restart dnsmasq
if [ $changed = true ]
then
systemctl restart dnsmasq
fi
${SLEEP} $INTERVAL
done
次に、nginxコンテナを--dns Host-ip-address
で開始します。ここで、Host-ip-address
は、インターフェースdocker0
上のホストのIPアドレスです。
Nginx設定 は名前を動的に解決する必要があります:
server {
resolver Host-ip-address;
listen 80;
server_name @server_name@;
root /var/www/@root@;
index index.html index.htm index.php;
location ~ ^(.+?\.php)(/.*)?$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$1;
set $backend "@fastcgi_server@";
fastcgi_pass $backend;
}
}
参照:
Nginxとphp-fpmが異なるホストにある場合は、@ smajの答えを試すことができます。
別のアプローチは、 consul-template のようなものを調べることです。
そしてもちろん、ある時点で Kubernetes について言及する必要があるかもしれません。
ただし、Dockerイベントを使用して何ができるかを調べることで、少し文字列とダクトテープのアプローチを検討できます(簡単なサンプルの場合はdocker events --since 0
を実行してください)。
これらのイベントを確認するスクリプト(python、goなどを含むいくつかのクライアントパッケージが利用可能であることを念頭に置いてください)、構成ファイルを修正し、nginxを再読み込みする(つまり、consul-templateアプローチを使用する)ことは、かなり簡単です。領事は必要ありません)。
ただし、元の前提に戻るには、php-fpmコンテナーが独自のネットワークで開始されている限り(つまり、nginxのような別のコンテナーのネットワークを共有していない場合)、ポートでリッスンするコンテナーをいくつでも持つことができます。必要に応じて9000-コンテナごとのIPがあるため、ポートの「衝突」の問題はありません。
これをどのようにスケーリングするかは、最終的な目標やユースケースによって異なりますが、検討する必要があるのは、nginxとphp-fpmノードの間にHAproxyを配置することです。これにより、php-fpmサーバー(つまり172.18.0.0/24)の範囲を指定し(場合によってはdocker network
を作成し)、HAproxyを設定して、バックエンドとしてのその範囲。 HAproxyはヘルスチェックを備えているため、どのアドレスがライブであるかをすばやく特定し、それらを利用できます。
Nginxとhaproxyがアップストリームをどのように処理するかについての議論は https://stackoverflow.com/questions/1358198/nginx-removing-upstream-servers-from-pool を参照してください。
これに専用のDockerネットワークを使用していない限り、php-fpmノードの手動IP管理をmightする必要があります。
この投稿は2015年のものであり、私はネクロイングしているように感じます(ごめんなさいコミュニティ)、この時点で追加することは貴重だと感じています。
今日(そしてKubernetesが言及されて以来)、Dockerを使用しているときは、KubernetesまたはDocker Swarmを非常に簡単に使用してこの問題を解決できます。両方のオーケストレーターがDockerノード(1つのノード= Dockerを搭載した1つのサーバー)を取り込み、それらにオーケストレーターをデプロイして、オーバーレイネットワークを使用してポートの課題を管理します。
私はDocker Swarmに精通しているので、次の方法でこの問題に対処します(単一のDockerノードがあると想定しています)。
スウォームを初期化します。
docker swarm init
プロジェクトルートにcdします。
cd some/project/root
(docker-composeを使用する代わりに)docker-compose.ymlからスウォームスタックを作成します。
docker stack deploy -c docker-compose.yml myApp
これにより、「myApp」と呼ばれるdocker swarmサービススタックが作成され、ポートが管理されます。つまり、docker-composeファイルのphp-fpmサービスに "port:9000:9000"定義を1つ追加するだけで、php-fpmサービスを3つのインスタンスに拡張できます。 3つのインスタンス間でリクエストを自動的に負荷分散し、追加の作業は必要ありません。