フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

Dockerで即席HTTPSエンドポイント

エンジニアの佐藤です。こんにちは。

先日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にアクセスすると…できました! f:id:masashi-sato-flect:20170520131643p:plain

yumやaptでインストールする場合と比べてどうか

Nginxはyumやaptといったパッケージマネージャでも容易にインストールできます。設定の手間はというと、実はほとんど同じです。 ではDockerを使うメリットは何かというと、「まるごと捨てられる」という点だと思います。筆者はローカルマシンのアプリが増えるのを好みません。Dockerコンテナなら、ホスト環境を汚染しませんし、問題があったらコンテナ削除で完全にリセットできます。

開発環境ではELBの代わりに

ELBはAWSが提供するロードバランサで、無料証明書が使えたりして便利なのですが、そこそこの費用がかかります。本番環境ならELBが適当でしょうが、開発用ではそこまでの設備は不要です。どこかに間借りして今回のnginxコンテナを上げれば十分でしょう。