やりたいこと
自分はさくらのVPSを借りて複数のサービスを運営している。
本当なら1つのサービスに対して1台のVPSを契約するのが理想だが、趣味の開発なのでそこまでお金はかけられない。
なので1台のVPS上に複数のコンテナを立ち上げて、nginxのリバースプロキシを使ってアクセスを振り分けるという形式を採用している。
例えばhttps://a.zurukumo.dev
へのアクセスはコンテナAに、https://b.zurukumo.dev
へのアクセスはコンテナBに振り分けるというような感じだ。
nginxの設定もSSL証明書の発行も手動で実行していたが、だんだんめんどくさくなってきたので、もっと楽にできる方法がないか調べてみた。
そこで発見したのがnginx-proxy
とacme-companion
というDockerイメージだった。
この2つのイメージを組み合わせることで、最小限の設定でリバースプロキシの設定からSSL証明書の発行までを自動化することができた。
今回の記事はその方法のご紹介である。
方法
まず、ざっくりとした構成を仮定する。
kagoとnbamashという2つのサービスを運営していて、どちらのサービスもwebコンテナ + dbコンテナという構成である。
両サービスともdocker composeで立ち上げているとする。
ここでhttps://kago-api.zurukumo.dev
へのアクセスはkagoのwebコンテナに、https://nbamash-api.zurukumo.dev
へのアクセスはnbamashのwebコンテナに振り分けることを目標にする。
1. DNSに利用したいドメインを登録しておく
向き先はVPSのIPアドレスにする。
自分の場合はこんな感じ(黒塗りの部分は両方同じIPアドレス)。
2. ネットワークを作成する
nginx-proxyとacme-companionは動いてるDockerコンテナを検知すると自動でプロキシの設定やSSL証明書の発行を行ってくれる。
動いているコンテナを検知できるようにするるために、nginx-proxyとacme-companionを各種サービスと接続するためのネットワークを作成する。
docker network create proxy
今回はproxyという名前のネットワークを作成したが、名前はご自由に。
3. リバースプロキシ&SSL証明書取得用のdocker-compose.ymlを作成する
公式GitHubのDockerコマンドをdocker-compose.yml
に素直に書き換えた上で、networksの設定だけ追加した。
services:
proxy:
image: nginxproxy/nginx-proxy
ports:
- 80:80
- 443:443
volumes:
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- proxy
cert:
image: nginxproxy/acme-companion
volumes_from:
- proxy
volumes:
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- DEFAULT_EMAIL=(自分のメールアドレス)
networks:
- proxy
volumes:
certs:
html:
acme:
networks:
proxy:
external: true
HTTP-01 チャレンジに80番ポートを使用するため、80番ポートを開放している。
もしファイアフォールなどで80番ポートを閉じている場合は、開放しておく必要がある。
4. 各種サービスのdocker-compose.ymlを微修正する
例えば以下のようなkago用のdocker-compose.yml
があるとする。
services:
web:
(...中略...)
db:
(...中略...)
nginx-proxyとacme-companionがkagoのwebコンテナを検知できるようにネットワークを追加する。
services:
web:
(...中略...)
networks:
- default
- proxy
db:
(...中略...)
networks:
- default
networks:
proxy:
external: true
ここでnetworksにproxyだけでなくdefaultも指定している。
docker composeはデフォルトでdefaultというネットワークを作成してくれて、そのおかげで特に設定せずともwebコンテナとdbコンテナが接続できている。
しかし、今回はnetworksに明示的にproxyを設定したことで、defaultの設定がスキップされてしまう。
そこでdefaultの設定も明示的に指定して、webコンテナとdbコンテナの通信経路を確保している。
5. SSL証明書の発行用の環境変数の設定
各種サービスのwebコンテナに以下に示す環境変数を設定する。
この設定を行うことでacme-companionが自動でkago-api.zurukumo.dev
用のSSL証明書を発行してくれる。
ちなみにVIRTUAL_PORT
はサーバが80番ポートで動いている場合のみ省略可能。
services:
web:
(...中略...)
environment:
- VIRTUAL_HOST=kago-api.zurukumo.dev
- VIRTUAL_PORT=8000
- LETSENCRYPT_HOST=kago-api.zurukumo.dev
networks:
- default
- proxy
db:
(...中略...)
networks:
- default
networks:
proxy:
external: true
6. コンテナを立ち上げる
あとはproxy/docker-compose.yml
、kago/docker-compose.yml
、nbamash/docker-compose.yml
をそれぞれ立ち上げるだけである。
まとめ
こんなに便利なDockerイメージがあるんですなあ…。
Comments