Nginxの設定とCertbotという悪夢
Nginxは今でも金字塔的な存在ですが、正直なところ、何百行にも及ぶ設定ファイルの管理は苦行です。以前、Dockerで動かしているサブドメインのSSLをCertbotで更新しようとして、デバッグに3時間も費やしたことがあります。問題の多くは、Nginxによる本番環境へのデプロイでよく遭遇するリダイレクトルールの重複や.well-known設定のミスにありました。
5〜10個のマイクロサービスを管理している場合、proxy_passやheader、ssl_certificateの設定を何度も繰り返すのは時間の無駄です。そこで救世主として現れたのがCaddyです。Caddyはすべてを手動で行うのではなく、デフォルトですべてを自動化すること、特にAutomatic HTTPSに重点を置いています。追加のプラグインなしで、Let’s EncryptからのSSL証明書の発行と更新をすべて自動で行ってくれます。
なぜ Docker環境でCaddyがNginxを凌駕するのか?
- 超シンプルな設定: 完全なHTTPS対応サイトが、わずか3行のコードで構築できます。
- デフォルトでHTTP/3対応: Caddyは標準でHTTP/3 (QUIC) をサポートしており、従来のHTTP/2よりもページの読み込み速度が約20〜30%向上します。
- SSLの100%自動化: Certbotのことは忘れてください。Caddyが証明書の取得から、期限が近づいた際の更新まで、AからZまですべて処理します。
- Go言語製: システムライブラリに依存せず、コンテナ内で単一のバイナリとして非常に軽量に動作します。
ステップ1:共通のDockerネットワークを作成する
Caddyを「ゲートキーパー」として機能させるには、他のコンテナと通信するための専用の経路が必要です。ここではcaddy_netという名前のネットワークを作成します。これによりシステムのセキュリティが向上します。内部のアプリはポートを外部に公開する必要がなくなり、ポート80と443からのトラフィックを受け取れるのはCaddyだけになります。
docker network create caddy_net
実際、この方法を導入したことで、データベースやRedisなどのサービスがネットワーク内に隠蔽され、ポートスキャンのリスクを最大90%削減することができました。Docker Bench for Securityなどのツールで診断すると、その効果がより明確になります。
ステップ2:Docker ComposeでCaddyをデプロイする
まず、すべての設定を保存するためのcaddyディレクトリを作成します。将来的にサービスが増える場合は、Docker Composeの最適化テクニックを利用してYAMLファイルを整理するのが効率的です。標準的なディレクトリ構造は以下のようになります:
caddy/
├── docker-compose.yml
└── Caddyfile
docker-compose.ymlの内容は以下の通りです:
version: "3.9"
services:
caddy:
image: caddy:2.7-alpine
container_name: caddy_proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3を有効にするために重要
networks:
- caddy_net
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
caddy_net:
external: true
volumes:
caddy_data:
caddy_config:
警告: /dataのボリュームマウントを絶対に忘れないでください。ここにはSSL証明書が保存されます。このデータを紛失した状態でコンテナの再起動を繰り返すと、証明書の発行要求が多すぎるとしてLet’s Encryptから7日間のIPブロック(Rate Limit)を受ける可能性があります。
ステップ3:Caddyfileの設定 — シンプルさの力
例えば、Django REST FrameworkのDocker化などで作成したアプリコンテナが、ポート3000で動いているとします。Nginxなら20行ほど必要ですが, Caddyならこれだけです:
app.yourdomain.com {
reverse_proxy my_awesome_app:3000
}
信じられますか?これだけです。CaddyはSSLが必要であることを自動的に理解し、証明書を申請し、プロキシを設定します。さらにセキュリティを強化し、Google PageSpeedを最適化するためにデータを圧縮したい場合は、以下の構造を使用します:
api.yourdomain.com {
encode gzip zstd
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options nosniff
}
reverse_proxy api_container:8080
}
ステップ4:起動とログの確認
以下のコマンドを実行してシステムを起動します:
docker-compose up -d
Caddyが正しく動作しているか確認するには、ログをチェックします。ctop: ターミナルでDockerコンテナをリアルタイム監視ツールを使用すれば、ログとリソース消費量を同時に確認できるので便利です。SSL証明書が発行されたかどうかを確認する方法は以下の通りです:
docker logs -f caddy_proxy
ログにcertificate obtained successfullyと表示されれば、ブラウザを開いて、苦労することなく緑色の鍵マークを確認できるはずです。
実践的なヒント:Caddyでエラーが発生した時は?
実際の運用で最も多いエラーは502 Bad Gatewayです。このエラーが発生した場合は、アプリケーションコンテナがcaddy_netに参加しているか確認してください。Caddyは見えないものに接続することはできません。
Cloudflareを使用している方への注意点:SSL/TLS設定を「Full (strict)」にしてください。「Flexible」に設定していると、CloudflareがサーバーにHTTPでリクエストを送るのに対し、CaddyがHTTPSを強制しようとするため、リダイレクトループ(Too many redirects)に陥ります。
Caddyは単なるツールではなく、よりスマートに働くための手段です。煩雑な設定に時間を費やす代わりに、インフラ部分はCaddyに任せ、皆さんはコードを書くことや製品の最適化に集中しましょう。

