【第1回】Docker + Nginxで構築するリバースプロキシとサブドメインルーティングの基本

このHPはアフィリエイトプログラムでの収益を得ています。

今回は、自宅サーバー(Ubuntu)上で複数のWebサービスをDockerコンテナとして稼働させ、Nginxを使って安全かつ効率的にルーティングする「リバースプロキシ」の構築方法をご紹介します。

システム構成の概要

当ブログのシステムは、以下のようなマイクロサービスアーキテクチャを採用しています。

  • メインブログ: Astro.js (https://example.com/)
  • アクセス解析: Umami (https://analytics.example.com/)
  • コメントシステム: Cusdis (https://comments.example.com/)

これらをホストOSのポートを直接公開せずに、Dockerの内部ネットワーク(proxy_net)内で通信させ、Nginxがアクセスを振り分ける構成にしています。

Dockerネットワークの準備

セキュリティを高めるため、各コンテナは内部ネットワーク経由でNginxと通信します。あらかじめ外部ネットワークを作成しておきます。

docker network create proxy_net

各サービスの docker-compose.yml では、このネットワークを指定します。

networks:
  proxy_net:
    external: true

Nginxの設定(default.conf)

Nginxで複数のサブドメインを管理するための設定ファイル(default.conf)の全容です。トラブルを避けるためのベストプラクティスを盛り込んでいます。

1. メインブログ(Astro)の設定

server {
    listen 80;
    listen [::]:80;
    server_name example.com;

    # 動的名前解決用リゾルバ(Dockerの内部DNS)
    resolver 127.0.0.11 valid=30s;

    # セキュリティヘッダー
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    location / {
        # 変数化して起動時のエラーを回避
        set $upstream_astro "http://astro-blog-app:4321";
        proxy_pass $upstream_astro;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        # WebSocket対応 (AstroのHMRや各種通信用)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

2. サブドメインのルーティング(アクセス解析&コメント)

UmamiやCusdisなどのバックエンドサービス向けの設定です。

# アクセス解析 (Umami)
server {
    listen 80;
    listen [::]:80;
    server_name analytics.example.com;
    resolver 127.0.0.11 valid=30s;

    location / {
        set $upstream_umami "http://umami-app:3000";
        proxy_pass $upstream_umami;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

# コメントシステム (Cusdis)
server {
    listen 80;
    listen [::]:80;
    server_name comments.example.com;
    resolver 127.0.0.11 valid=30s;

    location / {
        set $upstream_cusdis "http://cusdis-app:3000";
        proxy_pass $upstream_cusdis;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

構築時の重要なポイント

1. 動的名前解決の導入 (resolver 127.0.0.11)

Docker環境でNginxを運用する際、転送先のコンテナが再起動等でIPアドレスが変わると、Nginxが host not found in upstream などのエラー(502 Bad Gateway)を吐いてダウンすることがあります。 これを防ぐため、Docker標準のDNS(127.0.0.11)を指定し、proxy_pass の宛先を変数(set $upstream_...)で定義することで、Nginxの起動エラーを回避できます。

2. プロトコルの明示指定 (X-Forwarded-Proto https)

Cloudflareなどを前段に置いている場合、Nginx自体はHTTPで通信を受けていても、背後のNext.jsなどのモダンアプリに「これはHTTPS通信だ」と正しく教え込まないと、アプリ側で無限リダイレクトループ(ERR_TOO_MANY_REDIRECTS)を引き起こします。これを防ぐために明示的に指定しています。

おわりに

Nginxのリバースプロキシ設定は少し癖がありますが、一度ベストプラクティスな型を作ってしまえば、今後新しいサービスを追加する際もサブドメインのブロックを追加するだけで簡単に拡張できます。ホームラボを運用する上で欠かせない技術ですので、ぜひ参考にしてみてください。

📝
ブログを読む 技術記事や日々の記録
𝕏
𝕏 をフォロー 最新情報をチェック
✉️
お問い合わせ ご質問やご意見など