【HTTPS】設定方法 on Docker + Nginx + EC2

Docker
skylarvisionによるPixabayからの画像

こんな方が対象

  • Docker + NginxでWebサービスを構築したけど、運用するならhttps(SSL)に対応しないとと気づいた人(かく言う私もそうでしたw)
  • httpsの設定自体は運用サーバーでやったことがあるけど、Docker使う場合どうするの?
  • SSL証明書が切れる度にサイトにつながらなくなって、毎回手動で更新しているそこのあなた!(いないかw)
  • 運用サーバーに設置したけど、ローカル開発環境と差異ができて何かと作業しずらい

 ※私もサイト運用前に上記のような人だったので、設定手順の備忘録のため、記載します!

ウェブ開発の人気オンラインコース

設定前の環境

https対応(SSL対応)をする前の想定される環境は以下の通りです。

運用サーバー:AWS EC2 (これは、Dockerが動くなら特に何でもいいと思います)
Webサービス動作環境:Docker
Docker環境:
 Webサーバー:Nginx
 Webアプリ:PHP(Laravel)
 DB:MySql (これも、https対応には直接関係ないので無視してください)

プロジェクト全体のファイル構成:

プロジェクトルートフォルダ
 ┣ docker
 ┃  ┣ mysql
 ┃  ┃  ┗ my.cnf
 ┃  ┃
 ┃  ┣ nginx
 ┃  ┃  ┗ default.conf
 ┃  ┃
 ┃  ┗ php
 ┃      ┣ php.ini
 ┃      ┗ Dockerfile 
 ┃
 ┣ project
 ┃   ┗ myapp
 ┃       ┗ Laravelプロジェクト
 ┃
 ┣ docker-compose.yml
 ┗ .env (Docker用環境定義ファイル) 

(2023/05/18追記)下記にサンプルとして使っていただけるソースを配置しました!
フォーク等して自由に使ってください!

GitHub - friendsspring/docker-laravel-env
Contribute to friendsspring/docker-laravel-env development by creating an account on GitHub.

設定手順

docker-compose.yml 修正

まずは、docker-compose.ymlを下記のように修正する。
ポート番号と証明書,キーファイルを配置するための設定。

version: "3"
services:
  app:
    .....(Webアプリ環境なので省略)
  web:
    image: nginx:1.17-alpine
    depends_on:
      - app
    ports:
      - ${WEB_PORT}:443  <- 80番ポート(HTTP) を443(HTTPS)に変更
    volumes:
      - ${PROJECT_PATH}:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ${SSL_CRT_PATH}:/etc/nginx/certs/server.crt
      - ${SSL_KEY_PATH}:/etc/nginx/certs/server.key
      - ${SSL_PASS_PATH}:/etc/nginx/certs/server.password
      ↑ 証明書,キーファイル配置のため追加

${WEB_PORT}などの定義はDockerの.envファイルに記載

WEB_PORT=443
SSL_CRT_PATH=./docker/nginx/certs/server.crt
SSL_KEY_PATH=./docker/nginx/certs/server.key
SSL_PASS_PATH=./docker/nginx/certs/server.password

このポート番号が外部からアクセスされる際のポートになるので、AWSを使っているならセキュリティ設定で開ける必要がある。
証明書、キーファイルパスを.envに定義したのは、ローカルと運用サーバーの違いをこの.envファイルに集約するためです。

Nginxの設定ファイル(default.conf)の修正

次にNginxの設定ファイルを修正する。
こちらはコンテナ内部のポート番号の修正と、証明書,キーファイルのパスを設定する。

server {
    listen 443 ssl;  <- 80とかになっているはずなので、443 sslに修正
    server_name localhost; <- 定義してなかったら、一応定義
    root /work/myapp/public;
    index index.php;
    charset utf-8;
    .....
     ↓証明書,キーファイルの実際のパス指定
    # HTTPS用証明書とキーを設定 
    ssl_certificate     /etc/nginx/certs/server.crt;
    ssl_certificate_key /etc/nginx/certs/server.key;
    ssl_password_file   /etc/nginx/certs/server.password;
  ....

ローカル開発用の証明書とキーファイルをホスト側に配置

次に今まで何度も出てきている「証明書,キーファイル」を実際に配置する。
「ローカル開発用」とわざわざ明記したのは、なるべく運用サーバーと開発環境で差異をなくすため、ローカル環境でもhttpsでアクセスする環境を構築しようと思ったから。

プロジェクトルートフォルダ
 ┗docker
    ┗nginx
       ┗certs
          ┗ ここに配置していきます(コンソールとかでここに移動しておいてください)

配置するのは、以下の4つのファイルです。
実は、決まったコマンド打っていくだけなので、思ったより簡単です!

・server.key(秘密鍵)
・server.csr(公開鍵 + 認証局での署名に必要な情報)
・server.crt(サーバ証明書)
・server.password(秘密鍵用のパスワードを配置したファイル)

3ファイルを生成する際には、任意のパスワードが必要です。

server.key(秘密鍵)の作成

配置するディレクトリで下記コマンド打つだけ!(ただし、任意のパスワードを設定)

openssl genrsa -aes128 2048 > server.key

server.csr(公開鍵 + 認証局での署名に必要な情報)の作成

同じく、下記コマンド打つだけ!(ただし、パスワードを聞かれるので↑で設定したものを入力)

openssl req -new -key server.key > server.csr

と思いきや、何やら聞かれるので、下記のように入力

Contry Name:JP(日本以外なら、、適宜)
Common Name:ホスト名(例:hoge.example.com)

これ以外はEnterでOK!

server.crt(サーバー証明書)の作成

下記コマンド打つだけ!

openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt

server.password(秘密鍵用のパスワードを配置したファイル)

下記コマンド打つだけ! 任意のパスワードが「hogepass」の場合

echo hogepass > server.password

各ファイル生成後のフォルダ構成

このようになっているはず

プロジェクトルートフォルダ
  ┗docker
     ┗nginx
        ┗ certs
            ┣ server.crt
            ┣ server.csr
            ┣ server.key
            ┣ server.password
            ┗ .gitignore  <- キー情報をgithubとかに上げないように入れておきましょう
               運用サーバーでは別のキーになるので、
               それも踏まえてソース管理しない方が良い

.gitignoreの例

*
!.gitignore

Docker起動!

dokcer-compose up -d --buildとかでDockerを立ち上げて、https://localhost:80 (Dockerの.envに定義したポート) でアクセスして、サイトが表示されればOK!!

ここまでは、↓サイトを参考にさせていただきました!

Dockerを使ってローカルに立てたNginxでHTTPS通信する方法|Webエンジニア研究室
Dockerを使ってローカルに立てたNginxでHTTPS通信する方法を解説します。

運用サーバーでのキー配置について

ここからは、運用サーバー側でのキー配置についてです。
EC2(Amazon Linux2)を想定した手順を記載していきます。

certbotのインストール

下記コマンドで証明書取得のための、certbotをインストールします。

sudo amazon-linux-extras install -y epel
sudo yum install -y certbot

証明書の取得

下記コマンドで証明書を取得します。

sudo certbot certonly --standalone -n --agree-tos --email hoge@example.org -d hoge.example.com

実行すると、以下のパスに証明書が作成されます。

/etc/letsencrypt/live/hoge.example.org/fullchain.pem: 証明書
/etc/letsencrypt/live/hoge.example.org/privkey.pem: 秘密鍵

証明書の配置

Docker用の.envに証明書,鍵ファイルのパスを定義します。

SSL_CRT_PATH=/etc/letsencrypt/live/hoge.example.org/fullchain.pem
SSL_KEY_PATH=/etc/letsencrypt/live/hoge.example.org/privkey.pem
SSL_PASS_PATH=./docker/nginx/certs/server.password

中身が空のserver.passwordファイルを下記に配置します。

プロジェクトルートフォルダ
  ┗docker
     ┗nginx
        ┗ certs
            ┣ server.password <- 中身空で作成
            ┗ .gitignore  <- ローカル環境構築手順により、これだけソース管理されているはず

これで、docker-compose up -d すれば、httpsでアクセスできるはずです!!

証明書の自動更新設定

証明書は自動更新しないと、確か3ヵ月程度で有効期限が切れてしまいhttpsでアクセス不能になってしまいます。
これを自動的に回避するため、自動更新のcronに設定しておきます。

crontabの編集

sudo vim /etc/crontab

これで、crontabを開き

15 3 * * * root certbot renew && /usr/local/bin/docker-compose -f /home/ec2-user/(プロジェクトルートフォルダ)/docker-compose.yml restart web
                                                      ↑コンテナ名

の行を追加します。
これで、毎日深夜3:15に必要に応じて証明書を更新し、nginxの再起動が行われるようになります!

証明書の有効期限の確認方法

最後に証明書の有効期限の確認方法についてです。

sudo openssl x509 -in /etc/letsencrypt/live/hoge.example.org/fullchain.pem -noout -dates

このコマンドで表示される[notAfter]が期限です。

運用サーバーでの設定については下記サイトを参考にさせていただきました!

Let's Encrypt と Nginx を使った Web アプリの HTTPS 化 - Qiita
の続きです。AWS 上に docker-compose で自家用 redmine を作成…

少々長くなりましたが、httpsをローカルのdocker、さらに運用サーバーにて実現する1例について記載しました!

お試しあれ~

オススメ

コメント

タイトルとURLをコピーしました