はじめに
複数の Web サービスを同じサーバーで動かすとき、ポートや証明書の管理が面倒になりがちです。
そこで便利なのが nginx-proxy と acme-companion の組み合わせです。
- nginx-proxy : コンテナの環境変数 (
VIRTUAL_HOST
) を読み取り、自動的に Nginx のリバースプロキシ設定を生成 - acme-companion : Let’s Encrypt の証明書を自動発行・自動更新
これにより、サービス側にほとんど設定を書かずに 自動で HTTPS 化された環境を構築できます。
前提条件
- サーバー上に Docker / Docker Compose がインストール済みであること
- 公開するドメインがサーバーの グローバル IP に正しく向いていること
- すべてのサービスコンテナは 同じ Docker ネットワーク (
shared-net
など) に所属する必要があります
docker-compose.yml(プロキシ側)
以下は nginx-proxy
+ acme-companion
の基本構成です。
この 2 コンテナが 80/443 ポートを占有して、全サービスのフロントに立ちます。
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:alpine
container_name: nginx-proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /etc/nginx/certs:/etc/nginx/certs
- /etc/nginx/vhost.d:/etc/nginx/vhost.d
- /usr/share/nginx/html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- shared-net
labels:
com.github.nginx-proxy.nginx: "true"
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-acme
restart: always
depends_on:
- nginx-proxy
environment:
DEFAULT_EMAIL: 「メールアドレス」
NGINX_PROXY_CONTAINER: nginx-proxy
volumes:
- /etc/nginx/certs:/etc/nginx/certs
- /etc/nginx/vhost.d:/etc/nginx/vhost.d
- /usr/share/nginx/html:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- shared-net
networks:
shared-net:
external: true
サービスを追加する方法
公開したいサービスも 同じネットワーク (shared-net) に所属させる必要があります。
以下は Hugo で作ったブログを knowledge.sho-kun.com で公開する例です。
services:
hugo:
image: klakegg/hugo:ext-alpine # Hugoビルド用イメージ
container_name: hugo-builder
volumes:
- ./site:/src
working_dir: /src
command: ["hugo", "--minify"]
knowledge-blog:
image: nginx:alpine
container_name: knowledge-blog
restart: always
expose:
- "80" # nginx-proxy に公開するだけ
volumes:
- ./site/public:/usr/share/nginx/html:ro
environment:
- VIRTUAL_HOST=knowledge.sho-kun.com
- LETSENCRYPT_HOST=knowledge.sho-kun.com
- LETSENCRYPT_EMAIL=「メールアドレス」
networks:
- shared-net
networks:
shared-net:
external: true
VIRTUAL_HOST : サービスを公開するドメイン名
LETSENCRYPT_HOST : 証明書を発行するドメイン名(基本的に VIRTUAL_HOST と同じ)
LETSENCRYPT_EMAIL : 証明書発行に使うメールアドレス
networks : 必ず nginx-proxy と同じネットワークに入れることが重要です
注意点
nginx-proxy コンテナはサーバー全体の 80/443 ポートを占有するため、他のサービスで直接そのポートを使うことはできません。
ドメインの DNS がサーバーに正しく設定されていないと、Let’s Encrypt の認証に失敗します。
証明書発行には回数制限があるので、テスト時は Let’s Encrypt Staging 環境 を使うのがおすすめです。