Dockerローカル環境のHTTPS化:mkcertとNginxで「緑の鍵」を構築する

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

http://localhost:30008080での開発は、最初は特に問題ないように思えます。しかし、OAuth2やService Workerのテスト、外部サービスからのWebhook受信が必要になると状況は一変します。ローカル環境に適切なSSLがないと、ブラウザに警告が表示されるだけでなく、APIが接続を拒否することもあります。

以前は、OpenSSLを使って自己署名証明書(オレオレ証明書)を作成していました。しかし、アクセスするたびにChromeの「この接続ではプライバシーが保護されません」という警告を何度もクリックしなければならず、非常に面倒でした。その後、大規模なプロジェクトに携わる中で、mkcertとNginxリバースプロキシを組み合わせる手法に辿り着きました。この方法はスマートでプロフェッショナル、そして何よりすぐに「緑の鍵」が表示されます。

課題:なぜhttp://localhostだけでは不十分なのか?

ローカル環境でも最初からHTTPSをセットアップすべき、3つの現実的な理由があります:

  • 本番環境との整合性: デプロイ時の「Mixed Content」エラーを防ぎます。特にSecureSameSite=NoneといったCookieの属性は、HTTPS環境でなければ正常に動作しません。
  • 特定の機能への対応: Geolocation(位置情報)やプッシュ通知、あるいはNext.jsのようなモダンなフレームワークでは、セキュアコンテキスト(Secure Context)が必須となる場合が多いです。
  • 心理的効果: アドレスバーに表示される「緑の鍵」アイコンは、開発中の安心感とプロフェッショナルな気分を高めてくれます。

実際、Stripeの決済画面からのリダイレクト後にセッションが維持されないというエラーのデバッグに、丸一日費やしたことがあります。結局、原因はローカルのCookieにSecureフラグが欠けていたことでした。本物のHTTPS環境では必須となる設定が、ローカルでも必要だったのです。

必要なツール

開始する前に、以下の準備が必要です:

  1. Docker & Docker Compose: 標準的なアプリケーションのコンテナ化ツール。
  2. mkcert: コマンドひとつで信頼できるローカルCA(認証局)を作成できる「魔法」のようなツール。
  3. Nginx: リバースプロキシとして機能し、HTTPSトラフィックを受け取って各コンテナに振り分けます。

mkcert의インストール

macOSを使用している場合は、Homebrew経由でインストールできます:

brew install mkcert
brew install nss # Firefoxを使用する場合は必要

Windowsの場合は、Chocolateyを使用します:

choco install mkcert

インストール後、以下のコマンドを実行してローカルCAをシステムに登録します。この作業はPC一台につき一度だけ行えばOKです:

mkcert -install

実践:DockerプロジェクトのHTTPS化

ポート8080で動作しているアプリケーションがあり、仮想ドメイン itfromzero.test でアクセスしたいと仮定します。

ステップ1:SSL証明書の作成

プロジェクトディレクトリ内に、証明書を保存するフォルダを作成します:

mkdir -p certs
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem itfromzero.test "*.itfromzero.test" localhost 127.0.0.1

これで certs フォルダ内に2つの .pem ファイルが生成されます。注意:セキュリティのため、キーファイル(key.pem)は絶対にGitにコミットしないでください。

ステップ2:Nginxをリバースプロキシとして設定する

トラフィックを転送するための nginx.conf ファイルを作成します:

server {
    listen 80;
    server_name itfromzero.test;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name itfromzero.test;

    ssl_certificate /etc/nginx/certs/local-cert.pem;
    ssl_certificate_key /etc/nginx/certs/local-key.pem;

    location / {
        proxy_pass http://web_app:8080;
        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 $scheme;
    }
}

ステップ3:Docker Composeファイルの設定

ここで全てのコンポーネントを接続します。証明書ファイルと設定ファイルをNginxコンテナにマウントします。

version: '3.8'

services:
  web_app:
    image: nginx:alpine
    # アプリケーションはポート8080で待機中
    command: ["nginx", "-g", "daemon off;"]

  nginx_proxy:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - web_app

ステップ4:Hostsファイルの設定

itfromzero.test というドメインは実在しないため、PCがこのドメインをローカルIPに向けるように設定する必要があります。

Linux/macOSの場合は /etc/hosts、Windowsの場合は C:\Windows\System32\drivers\etc\hosts を開き、以下の行を追加します:

127.0.0.1 itfromzero.test

結果の確認

おなじみのコマンドでシステムを起動します:

docker-compose up -d

それでは、ブラウザで https://itfromzero.test にアクセスしてみましょう。追加のセキュリティ確認ボタンを押す必要なく、すぐに「緑の鍵」が表示されるはずです。

よくあるエラーと注意点

よく陥りがちな、3つの注意ポイントをまとめました:

  • ファイル権限: Linux環境でNginxが証明書を読み込めないエラーが出た場合は、chmod 644 certs/* を試して権限を再設定してください。
  • サービス名: Nginx設定内の proxy_pass は、docker-compose.yml で定義したサービス名と完全に一致させる必要があります。
  • DNSキャッシュ: hostsファイルを編集しても反映されない場合は、DNSキャッシュのクリア(flush DNS)やブラウザの再起動を試してください。

まとめ

mkcertを使用することで、ローカル開発環境が格段にプロフェッショナルになります。フレームワークや言語ごとに個別のSSL設定で悩む必要はありません。Nginxという一つの入り口さえあれば、全てのプロジェクトで標準的なHTTPS環境が手に入ります。ぜひ試してみてください!

Share: