この記事では、「ローカルにDockerで立てたNginx(エンジンエックス)でHTTPS通信する方法」を解説します。
記事の内容を実践すれば、ローカルにDockerで立てたNginxへのHTTPS通信が可能となるので、ぜひ参考にして頂けると嬉しいです。
nginx:1.21.3
HTTPS通信(SSL/TLS暗号化通信)の流れ
まずは、実際にNginxでどのような流れでHTTPS通信が行われるかを説明します。
クライアント・サーバ間のHTTPS通信(SSL/TLS暗号化通信)は以下の流れで行われます。
- クライアントがサーバに対してHTTPSでリクエストを送る
- サーバは公開鍵付きの証明書をクライアントに送付する(秘密鍵と違い、公開鍵は全世界にばら撒いて問題ない)
- クライアント側で生成した共通鍵を、公開鍵を使って暗号化する
- 暗号化した共通鍵をサーバに送付する
- 暗号化された共通鍵を秘密鍵で復号する
- クライアント・サーバ共に共通鍵を持っている状態となったので、共通鍵を使ったクライアント・サーバ間での暗号化通信が可能となる
事前にこのイメージを掴んでいたら、以降の実際の作業が理解しやすくなるはずです。
ちなみに、暗号化技術(共通鍵暗号方式と公開鍵暗号方式)については、以下の記事にまとめてあるので気になる方は読んでみて下さい。
Dockerを使ってローカルに立てたNginxでHTTPS通信する方法
HTTPS通信の流れが分かったところで、具体的にローカルにDockerで立てたNginxでHTTPS通信(SSL/TLS暗号化通信)するための手順を解説します。
まずはDockerでNginxを起動します。
version: '3.8' services: server: container_name: server build: ./docker ports: - 8081:80
FROM nginx
現状だと、http://localhost:8081にアクセスすると、以下のNginxのデフォルトページが表示されます。
しかしHTTPSには対応していないため、https://localhost:8081にアクセスしても何も表示されません。
ここからコードに設定を追加していくことで、https://localhost:8081でアクセスした際にNginxのデフォルト画面を表示させることを目指します。
NginxでHTTPSを利用するために必要なモジュールを追加
NginxでHTTPSを利用するためには、ngx_http_ssl_moduleが必要です。
しかし、Dockerイメージの場合は最初からこのモジュールは入っているため、新たにインストールする必要はありません。
公開鍵・秘密鍵・サーバ証明書をサーバ側で用意
次に、HTTPS通信で必要な公開鍵・秘密鍵・サーバ証明書をサーバ側で生成します。
実際に運用(本番環境等)でHTTPS通信をしたい場合は、証明書は認証局(Certificate Authority/CA)の署名が入ったものを使用する必要があります。
しかし、ローカルでHTTPS通信を試したい程度なら、自分で生成した(オレオレ)証明書を使っても問題ありません。
公開鍵・秘密鍵・サーバ証明書の生成には、OpenSSLコマンドを使います。このコマンドを使うことで、暗号化通信に必要なリソースを自分で用意することができます。
サーバ側では以下の3つのファイルを準備します。
- server.key(秘密鍵)
- server.csr(公開鍵+認証局での署名に必要な情報)
- server.crt(サーバ証明書)
それぞれのファイルを生成する際には、パスフレーズ(秘密鍵のパスワード)が必要です。任意の値を準備しておきましょう。
server.key(秘密鍵)の作成
まずは秘密鍵を作成します。
任意の(生成したファイルを配置したい)ディレクトリで以下のコマンドを打って下さい。
openssl genrsa -aes128 2048 > server.key
- genrsa:RSA形式の秘密鍵を作成する
- -aes128:128ビットのAES形式で暗号化
- 2048:2048バイト長の鍵を作成
server.keyファイルが作成されていたらOKです。
server.csr(公開鍵+認証局での署名に必要な情報)の作成
CSR(Certificate Signing Request)ファイルの作成には、以下のコマンドを使います。
openssl req -new -key server.key > server.csr
- req:CSRファイルを作成する際に指定
- -new:CSRを新規作成
- -key:秘密鍵ファイルを指定
ここでは、様々な情報の入力が求められると思います。
ほとんど何も入力しなくていいですが、Country Nameには国内ならJPを、Common nameにはドメイン名を含んだFQDN形式のホスト名(例:hoge.example.com)もしくはIPアドレスを指定しましょう。
あとは全部EnterでOKです。
server.crt(サーバ証明書)の作成
最後にサーバ証明書を作成します。
ここでは、公的機関ではなく、プライベートCAを使って証明書を発行します。(オレオレ証明書ですね)
以下のコマンドを打って下さい。
openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt
- x509:X.509形式の証明書を発行
- -in server.csr:CSRファイルを指定
- -days 365:証明書の有効期限を指定
- -req:入力ファイルがCSRファイルであることを示す
- -signkey server.key:秘密鍵ファイルを指定
server.crtが作成されたらOKです。
server.password(秘密鍵用のパスワードを配置したファイル)の作成
最後に、以下のコマンドで秘密鍵用のパスワードを配置したファイルを作成して下さい。(hoge123@の部分は自身の秘密鍵用のパスワードに書き換え)
echo hoge123@ > server.password
あとでHTTPS通信用のサーバー設定をする際に使います。
Nginxに秘密鍵と公開鍵を含んだサーバ証明書を配置する
証明書と秘密鍵の作成が終わったら、それらをコンテナ内に配置する処理を追加します。
また、HTTPS通信用にDockerfileやdocker-compose.yamlの記述も書き換えます。
最終的なディレクトリ構成は以下になる想定です。
最初にDockerfileを以下のように書き換えて下さい。
FROM nginx COPY nginx/ssl/server.crt /etc/nginx/ssl/server.crt COPY nginx/ssl/server.key /etc/nginx/ssl/server.key COPY nginx/ssl/server.password /etc/nginx/ssl/server.password
COPYコマンドで、先ほど作成した「証明書・秘密鍵・秘密鍵用のパスワードが書かれたファイル」をそれぞれコンテナ内にコピーしています。
次に、ssl.conf(HTTPS通信用のサーバー設定ファイル)を作成して下さい。
server { listen 443 ssl; root /usr/share/nginx/html; index index.html; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_password_file /etc/nginx/ssl/server.password; }
listenはこのサーバーが受け入れるポートです。HTTPS通信なので443を指定しています。
また、後ろの「ssl」は、指定した443番ポートでHTTPS通信を有効にするための設定です。
これが無いとHTTPSで通信できないので、しっかりと指定するようにしましょう。
rootとindexは、通信が上手くいった場合に画面に表示するNginxのデフォルトファイルを指定しています。
ssl_certificateにはサーバ証明書が配置していある場所のパス(先ほどDockerfileで指定したコンテナ側のパス)を指定しています。
ssl_certificateは秘密鍵が配置してある場所のパスです。
ssl_password_fileには秘密鍵用のパスワードが書かれたファイルのパスを指定しています。
nginxで秘密鍵を使用するためには、事前にパスフレーズを解除しておくか、ssl_password_fileディレクティブを用いてパスワードが書かれたファイルを指定する必要があるため、今回はパスワードが書かれたファイルを指定しています。
最後にdocker-compose.yamlです。以下のように記述して下さい。
version: '3.8' services: server: container_name: server build: ./docker ports: - 8081:443 volumes: - ./docker/nginx/ssl.conf:/etc/nginx/conf.d/ssl.conf
HTTPS通信のため、コンテナ側のポートには443を指定しています。
また、volumesで先ほど作成したssl.confをコンテナ内に配置しています。
HTTPS通信をするために必要な設定は以上です。
Dockerコンテナを立ち上げてHTTPSでアクセスする
最後に、docker-compose up -d --build
でコンテナを立ち上げ直して、HTTPS通信ができるか確認しましょう。
https://localhost:8081でアクセスしてNginxのデフォルト画面を表示させることができました。(URLの部分に鍵マークが付いています)
最終的なソースコードまとめ(証明書以外)
最後に、今回作成した(証明書や秘密鍵以外の)ファイルをまとめておきます。
基本的には、暗号化通信に必要なファイル(server.crt/server.key/server.password)を配置した上で以下のファイルをコピペしたら動くと思います。
version: '3.8' services: server: container_name: server build: ./docker ports: - 8081:443 volumes: - ./docker/nginx/ssl.conf:/etc/nginx/conf.d/ssl.conf
FROM nginx COPY nginx/ssl/server.crt /etc/nginx/ssl/server.crt COPY nginx/ssl/server.key /etc/nginx/ssl/server.key COPY nginx/ssl/server.password /etc/nginx/ssl/server.password
server { listen 443 ssl; root /usr/share/nginx/html; index index.html; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_password_file /etc/nginx/ssl/server.password; }
【Nginx】ローカルに立てたDockerコンテナでHTTPS通信する方法 おわりに
今回はNginxでのHTTPS通信(SSL/TLS暗号化通信)の流れと、ローカルDocker環境のNginxでHTTPS通信する手順を解説しました。
この記事が少しでも参考になっていれば幸いです。