はい、nginx をフロントエンドのリバースプロキシサーバーとして使用すれば、本番環境でも完璧に動作します。
私の構成は以下の通りです。
3 つのコンテナ:
- Data (data.yml)
- Socket1 (socket1.yml)
- Socket2 (socket2.yml)
nginx configでは、単一の UNIX ドメインソケットを指定します。例:
location / {
proxy_pass http://unix:/var/run/nginx.http.sock;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
}
その後、実際のソケットへの記号リンク(シンボリックリンク)を設定することで、ライブ化したいコンテナを選択します。
例えば、socket2コンテナをライブ化したい場合:
ls -sf /var/discourse/shared/socket2/nginx.http.sock /var/run/nginx.http.sock
socket1に変更を加え、socket1をライブ化したい場合:
cd /var/discourse
./launcher rebuild socket1
ls -sf /var/discourse/shared/socket1/nginx.http.sock /var/run/nginx.http.sock
socket1コンテナのみをブートストラップする必要はありません。なぜなら、コンテナは独自の共有ディレクトリ/ボリューム内の UNIX ドメインソケット経由で公開されるため、両方の「Web アプリ」コンテナを同時に実行できるからです。
- Socket1: /var/discourse/shared/socket1/nginx.http.sock
- Socket2: /var/discourse/shared/socket2/nginx.http.sock
これは、TCP/IP コンテナポートを公開した場合のような「ポートバインディングの競合」が発生しません。このため、本番環境では TCP/IP ポートではなく、UNIX ドメインソケットのみを公開しています。
もちろん、必要であればブートストラップを実行することも可能です:
cd /var/discourse
./launcher bootstrap socket1
./launcher start socket1
ls -sf /var/discourse/shared/socket1/nginx.http.sock /var/run/nginx.http.sock
どちらの方法を選んでも構いませんが、両方のコンテナを同時に実行すると、両方ともsidekiqを実行し、スケジュールされたジョブも実行される点に注意してください。私たちの経験では、そのため両方のコンテナ間でアップロードファイルを定期的に同期させています。
この方法で私たちは完璧に運用しており、Web アプリコンテナを再構築してライブ化する場合でも、実質的にダウンタイムゼロで実現できます。私たちは本番環境でのダウンタイムを非常に重視しており、可能な限り避けるようにしています。
注:
上記の方法は、ソリューションの Web アプリ部分向けに設計されたものであり、データコンテナ用ではありません。データコンテナ向けの同様のソリューションは作成していませんが、将来的にはデータコンテナ向けに(もちろん異なる形で)何らかのものを作成するかもしれません(「2 つのデータコンテナで DB を同期させる方法」など、現時点では完全に未定です)。
つまり、私は実際にはこれと逆のことをしています:
前述の通り、開発環境では問題なく動作します。
一般的に、私は開発環境ではこの設定を行いません。設定に時間がかかるためです。また、開発環境では少しのダウンタイムでも問題ないため、この設定は不要です(「私とコード」だけで、ユーザーやボットがサイトにアクセスしているわけではないため)し、さらに私は開発(デスクトップ上)では Docker を使用していません。
参考になれば幸いです。
ここで言う「開発」とは、ソフトウェア(例えばプラグイン)の開発を指します。単に Discourse インストールを「ステージング」することを指すわけではありません(「ステージング」と呼んでいます。念のため明確にしておきます)。