はじめに

複数の Web サービスを同じサーバーで動かすとき、ポートや証明書の管理が面倒になりがちです。

そこで便利なのが nginx-proxyacme-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 環境 を使うのがおすすめです。