エンジニアの佐藤です。こんにちは。
先日Java Springフレームワークで、とあるWebサーバをテストしていた時のことです。 ふと「HTTPSでテストしたい」と思い立ちました。
ところがです。
よく考えてみると筆者は、しばらくの間WebサーバーにHTTPSエンドポイントを設定した覚えがありません。今日ではWebサーバーがHTTPSを直受けすることはまれで、ロードバランサがHTTPSを受け、配下のWebサーバーはHTTPで機能実装というパターンがほとんどです。(このような時代の変化もあってか、近頃はググってもWebサーバーにHTTPSエンドポイントを設定するトピックは減ってきたように思います。) 今回の案件もそうでしたので、ならばできるだけ小さい作業負担で、HTTPSを受けてHTTPにしてくれる仕掛けを設定…と考えてDockerを活用することを思いつきました。今回はこのトピックをお話したいと思います。
要するにHTTPSでリクエストを受け、HTTPのパス全体(/)をHTTPで別サイトに投げるWebサーバー、つまりリーバスプロキシサーバー(リバプロ) なら良いのです。 そこで筆者の頭に思い浮かんだのは、nginxです。(そう言えばこれに近いGoogle Cloud Platform のCloud Endpoint は、nginxベースだと書いてありました。)
Dockerコンテナは…と思うと、ありました。同じことを考える人はたくさんいたようです。 https://hub.docker.com/_/nginx/
読み進めていくと、まさに今回の用途にピッタリの使い方が書いてあります。設定ファイルを用意するだけで、コマンド一発で即スタートというありがたさです。
$ docker run -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx
あとはオレオレ証明書と設定ファイルです。オレオレ証明書の作成は割愛しますが、設定ファイルnginx.confは以下のようにしました。
http { server { listen 443; ssl on; ssl_certificate /etc/secrets/proxycert; ssl_certificate_key /etc/secrets/proxykey; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-RC4-SHA:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!CAMELLIA; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; location / { proxy_pass http://localhost:8080/; } } } events { }
証明書と秘密キーをマッピングするオプションを追加した以下のコマンドでスタート。(ここでは「—network host」スイッチで、コンテナをホストのネットワークに直付けします。)
$ docker run -d --network host -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -v /host/path/cert.pem:/etc/secrets/proxycert:ro -v /host/path/key_nopass.pem:/etc/secrets/proxykey:ro nginx
開発中のWebサーバーをlocalhost:8080で待機させてからhttps://localhostにアクセスすると…できました!
yumやaptでインストールする場合と比べてどうか
Nginxはyumやaptといったパッケージマネージャでも容易にインストールできます。設定の手間はというと、実はほとんど同じです。 ではDockerを使うメリットは何かというと、「まるごと捨てられる」という点だと思います。筆者はローカルマシンのアプリが増えるのを好みません。Dockerコンテナなら、ホスト環境を汚染しませんし、問題があったらコンテナ削除で完全にリセットできます。
開発環境ではELBの代わりに
ELBはAWSが提供するロードバランサで、無料証明書が使えたりして便利なのですが、そこそこの費用がかかります。本番環境ならELBが適当でしょうが、開発用ではそこまでの設備は不要です。どこかに間借りして今回のnginxコンテナを上げれば十分でしょう。