nginx-proxy は Docker コンテナ用のリバースプロキシ
Docker コンテナイメージの nginx-proxy を使うと、複数の Docker コンテナ用のリバースプロキシを簡単に立ち上げることができます。
例えば、1 つの VPS サーバー上で複数の Docker コンテナー(例えば Web サーバー)を立ち上げるような場合は、次のような感じで入り口にリバースプロキシを配置し、そこから各 Web サーバーにアクセスを振り分ける構成にします。
ここでは、aaa.example.com
と bbb.example.com
というサブドメインにより、プロキシ先を振り分けるようにしていますが、example.com
というベースドメインを使うこともできます。
もともと Nginx でリバースプロキシを設定するのはそれほど難しくはないのですが、どうしてもその背後にあるコンテナーの設定がリバースプロキシ側の設定に染み出してしまいます。 また、リバースプロキシ用のコンテナーを最後に起動するという手順の複雑さもあります。
- 参考: Nginx でバーチャルホストを設定する(リバースプロキシ)
- 参考: Docker Compose でリバースプロキシを立てて別の Docker Compose 内のコンテナに接続する - まくまく Docker ノート
nginx-proxy
によるリバースプロキシを起動しておくと、背後でコンテナーを起動するだけで、自動的にリバースプロキシのエントリに追加してくれます。
nginx-proxy
には次のような利点があります。
- 背後の Docker コンテナの存在を意識しなくてよい(同一の Docker ネットーワーク内のコンテナ起動を検出して、自動的にリバースプロキシ設定に反映してくれます)
- 各サブドメイン用の SSL 設定(HTTPS 対応)を自動で行ってくれる(acme-companion を組み合わせて使用することで、Let’s Encrypt による SSL 証明書の取得を自動化できます)
リバースプロキシの設定更新が自動化されているので、Web アプリ用の Docker コンテナーを簡単に追加・削除できます。
事前準備
nginx-proxy
の設定を行う前に、サブドメイン用の DNS 設定や、80/443 ポートの解放などを行っておく必要があります。
ネットワーク的に繋がらないとどうしようもないですからね。
サブドメインの DNS 設定
独自ドメインの DNS 設定で、サブドメイン用の A レコードを追加して IP アドレスに関連づけておきます。 下記は ConoHa VPS での DNS 設定例ですが、だいたい同じような感じで設定できるはずです。
反映されるまで数分待ってから、DNS の A レコードを正しく引けるか確認しておきます。
例えば、dig
コマンドの出力の status:
が NOERROR
になっていれば正しく設定されています(もっと簡単に nslookup
や ping
で正引きできるかを確認するのでも OK です)。
## A レコードが正しく設定されている場合
$ dig A aaa.example.com | grep status
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55073
## A レコードが設定されていない場合
$ dig A aaa.example.com | grep status
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 55073
http/https 用のポート解放
対象のサーバー(VPS など)のファイアウォール設定で、外部からの 80 番ポート (http) および 443 番ポート (https) へのアクセスを許可しておきます。
まずは http 接続で試してみる
まずは nginx-proxy
の基本的な動かし方を理解しましょう。
SSL を使わない http ベースの接続であれば簡単に試せます。
下記は、nginx-proxy
コンテナーを起動するための Docker Compose ファイルです。
volumes:
プロパティで docker.sock
ファイルをマウントしているのは、nginx-proxy
が他のコンテナーの起動を監視して情報を取得するためです。
次のようにしてリバースプロキシを起動できます。
あとは、リバースプロキシの中継先となる Docker コンテナーを起動していくだけです。
このとき、バーチャルホスト名をコンテナー側の VIRTUAL_HOST 環境変数で設定することで、nginx-proxy
が自動的にその情報をリバースプロキシ設定に反映してくれます。
例えば、簡単な Web サーバーを起動する場合は次のようにします。
リバースプロキシと同じ nginx-proxy
ネットワークに接続する ことに注意してください(これを忘れると、アクセス時に 502 Bad Gateway エラーになります)。
ここでは接続確認だけしたいので、Ctrl-C
で停止できる形でコンテナを起動します(-d
オプションをつけません)。
Web サーバーを起動したら、Web ブラウザから http://aaa.example.com
という URL でアクセスして、Welcome to nginx! のページが表示されれば成功です。
次のステップ(SSL 証明書の自動設定)に進む前に、リバースプロキシを停止しておきましょう。
$ cd nginx-proxy
$ docker compose down
本番用の設定(SSL/TSL 対応)
nginx-proxy
と合わせて acme-companion
という Docker コンテナイメージを使うと、SSL 証明書の設定まで自動化できます(https によるアクセスが可能になります)。
Let’s Encrypt による SSL 証明書発行処理のために、nginx-proxy
コンテナーの方にもいくつかボリューム設定を追加する必要があります(本家サイトの説明通りに設定しています)。
ボリューム設定が若干ややこしいですが、接続先のコンテナーの情報がまったく出てこないのが素晴らしいです。
つまり、この docker-compose.yml
ファイルは、みなさんの環境でもそのまま使い回すことができます。
先ほどと同様に、nginx-proxy
コンテナーを起動します。
今回は https 対応版になっています。
中継先のコンテナーを立ち上げる
例: Web サーバー (nginx)
中継先のコンテナー(ここでは Web サーバー)を立ち上げるときは、Let’s Encrypt 用の設定値として LETSENCRYPT_HOST
と LETSENCRYPT_EMAIL
を指定します。
これらは、SSL 証明書の発行時に使用されます。
このコンテナを起動すると、自動的に Let’s Encrypt から SSL 証明書が発行されてリバースプロキシサーバーに設定されます。
これで、Web ブラウザから https://aaa.example.com
というアドレスでアクセスできるようになります。
例: Meilisearch サーバー
もうひとつ例として、インクリメンタルサーチエンジンの Milisearch サーバーを立ち上げる例を示しておきます。
こちらは、ドメイン名(バーチャルホスト)として bbb.example.com
を設定しています。
下記の例では environment
プロパティをリスト形式で設定していますが、前述のマップ形式での指定方法と意味は同じです。
ポートフォワードの設定 (ports
) で 7700:7700
と指定していますが、バーチャルホストを使った URL アクセス時には、80 番ポートの URL でアクセスすることができます。
つまり、https://bbb.example.com/
というアドレスで、コンテナー内の Meilisearch サーバーにアクセスすることができます。
このあたりのデフォルトのポートフォワード処理は nginx-proxy
がやってくれるので、実は ports
プロパティの設定は省略できたりします(Docker ホスト上で localhost:7700
のようにアクセスしたい場合は必要)。
(おまけ)nginx の設定を変更する
nginx 自体の設定を変更したいときは、Docker ホスト上に設定ファイルを作成しておいて Docker コンテナにバインドマウントします(参考: nginx-proxy/docs)。
ファイルの配置方法はいくつかありますが、/etc/nginx/conf.d
ディレクトリ以下に .conf
ファイルを配置するのが簡単です。
下記は、nginx サーバーの client_max_body_size
値をカスタマイズする設定ファイルの例です。
この値のデフォルト値は 1M になっているため、POST リクエストで大きなデータを送りたい場合はこのように大きめのサイズを指定しておく必要があります。
設定ファイルを用意したら、あとは docker-compose.yml
の volumes
セクションにバインドマウントの設定を追加するだけです。
docker compose up -d
を再実行すれば、nginx-proxy
コンテナーを新しい設定で起動できます。
まとめ
長々と説明してきましたが、結局のところ nginx-proxy
を一度導入してしまえば、あとは中継先のコンテナーを起動するときに、VIRTUAL_HOST
や LETSENCRYPT_HOST
を指定するだけでインターネットから https (SSL) でアクセスできるようになる ということですね。
これで、Docker コンテナーを使ったサービスをいくつでも簡単に公開できるようになります。
٩(๑❛ᴗ❛๑)۶ わーぃ
みんなも VPS を借りて遊んでみよー(これは宣伝です( ̄∇ ̄) → ConoHa の VPS )