Docker - nginx と php-fpm を個別にスケーリングする

Docker - nginx と php-fpm を個別にスケーリングする

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

1 つの解決策は、docker-compose ファイルに php-fpm インスタンスを追加し、他の回答で述べたように nginx アップストリームを使用してそれらの間で負荷分散することです。これは、次の例の docker-compose リポジトリで実行されます。nginx の php ファイルを .php ファイルにコピーします。

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 ポートはコンテナ内部のものであり、実際のホストのものではないことに注意してください。そのため、ポート 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/#ロードバランサー

2017/03/06更新:私は、インターロックDockerと連携してnginxの設定を自動的に更新し、再起動します。@iwaseatenbyagrueの答え追加のアプローチがあります。

答え2

この投稿は 2015 年のものであり、私はそれを否定しているように感じますが (コミュニティの皆さん、申し訳ありません)、この時点で追加することは価値があると感じています。

現在 (Kubernetes が話題になって以来)、Docker で作業しているときは、Kubernetes または Docker Swarm を使用してこの問題を簡単に解決できます。両方のオーケストレーターは Docker ノード (1 つのノード = Docker がインストールされている 1 つのサーバー) を取り込み、それらにサービスをデプロイできます。また、オーケストレーターはオーバーレイ ネットワークを使用してポートの課題を管理します。

私は Docker Swarm に精通しているので、この問題に対処するには次のようにします (Docker ノードが 1 つあると仮定)。

群れを初期化します:

docker swarm init

プロジェクトのルートにcdする

cd some/project/root

docker-compose.yml から swarm スタックを作成します (docker-compose を使用する代わりに):

docker stack deploy -c docker-compose.yml myApp

これにより、「myApp」という docker swarm サービス スタックが作成され、ポートが管理されます。つまり、docker-compose ファイルで php-fpm サービスに「port: 9000:9000」定義を 1 つ追加するだけで、php-fpm サービスを 3 つのインスタンスにスケールアップでき、swarm はそれ以上の作業を必要とせずに、3 つのインスタンス間でリクエストの負荷を自動的に分散します。

答え3

ここで説明するように、アップストリームを使用して複数のバックエンドを定義できます。

https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx

また、新しいバックエンドが停止したり、サービスを開始したりするたびに、次のように構成を更新する必要があります。

https://github.com/kelseyhightower/confd

答え4

別のアプローチとしては、次のようなものを検討するのもいいでしょう。領事テンプレート

そしてもちろん、ある時点で、クベネフィット言及する必要があるかもしれません。

ただし、Docker イベントを使用するとどのような効果が得られるかを検討することで、もう少し「糸とダクトテープ」を使ったアプローチを検討することもできます (docker events --since 0簡単なサンプルを実行する)。

これらのイベントを調べるスクリプト (Python、Go などを含む複数のクライアント パッケージが利用可能であることを念頭に置いてください) を用意し、構成ファイルを修正し、nginx をリロードする (つまり、consul テンプレート アプローチを使用しますが、consul は必要ありません) ことは、かなり簡単です。

ただし、元の前提に戻ると、php-fpm コンテナーが独自のネットワークで起動されている限り (つまり、nginx コンテナーなどの別のコンテナーのネットワークを共有していない限り)、ポート 9000 でリッスンするコンテナーをいくつでも持つことができます。コンテナーごとに IP があるため、ポートが「衝突」する問題は発生しません。

これをどのように拡張するかは、最終的な目標/ユースケースによって異なりますが、検討すべきことの 1 つは、nginx と php-fpm ノードの間に HAproxy を配置することです。これにより、docker networkphp-fpm サーバー (つまり 172.18.0.0/24) の範囲を指定 (場合によっては を作成) し、その範囲内の IP をバックエンドとして使用するように HAproxy を構成することができます。HAproxy にはヘルス チェック機能があるため、どのアドレスがアクティブであるかをすばやく識別し、それらを利用できます。

見るhttps://stackoverflow.com/questions/1358198/nginx-アップストリームサーバーをプールから削除するnginx と haproxy がアップストリームをどのように処理するかについての議論。

専用のDockerネットワークを使用していない限り、かもしれないphp-fpm ノードに対して手動で IP 管理を行う必要があります。

関連情報