Docker Compose で NGINX の起動前に自己署名証明書を生成する方法
Docker Compose で NGINX を起動する前に SSL/TLS の自己署名証明書を生成する方法についてです。
この方法は、開発環境や確認用の環境において http~
ではなく https~
のアドレスで動作確認をしたいときなどに有用です。
確認時の環境
- Docker:
Docker version 20.10.12, build e91ed57
- Docker Compose:
Docker Compose version v2.2.3
Docker Compose で NGINX の起動前に自己署名証明書を生成する方法
いろんなやり方がありますが、 Docker Compose の設定項目 depends_on
の service_completed_successfully
という condition を使えば比較的シンプルでかんたんに実現できるので今回はこの方法を説明します。
depends_on
に興味のある方には以下のページなども参考になるかと思います:
- このブログのまとめ記事: Docker Compose の depends_on の使い方まとめ
- 該当イシュー: Depends_on condition service_completed_successfully · Issue #8154 · docker/compose
以下やり方です。
- NGINX のコンテナとは別に証明書生成のためのコンテナを定義する
- NGINX のコンテナの起動条件として「証明書生成が正常終了していること」を追加する
具体的な設定ファイルのイメージは次のとおりです。
front
が NGINX を動かすためのコンテナに、 certs
が証明書を動かすためのコンテナに相当します。
docker-compose.yml
:
version: "3"
services:
# NGINX を動かす
front:
build: ./services/front
ports:
- "80:80"
- "443:443"
environment:
NGINX_SERVER_NAME: example.local
volumes:
- front_certs:/etc/ssl/certs/nginx:ro,cached
# NGINX の起動条件として「証明書生成処理が正常終了していること」を指定する
depends_on:
certs:
condition: service_completed_successfully
# 証明書を生成する
certs:
build: ./services/certs
environment:
DOMAIN: example.local
volumes:
- front_certs:/app:delegated
volumes:
# 証明書のファイルはボリュームで共有する
front_certs:
certs
サービスの Dockerfile
のイメージは次のとおりです。
Dockerfile
:
FROM alpine:latest
WORKDIR /app
RUN apk update && \
apk add openssl
CMD openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
-keyout domain.key \
-out signed.crt \
-subj "/CN=${DOMAIN}" \
-addext "subjectAltName=DNS:${DOMAIN}" \
-addext "extendedKeyUsage=serverAuth"
openssl
コマンドで証明書を生成してカレントディレクトリ( /app
)に保存します。
生成された証明書は Docker ボリュームを介して NGINX の front
コンテナに共有されます。
front
サービスの NGINX の設定ファイルの該当箇所のイメージは次のとおりです。
default.conf.template
:
server {
listen 80;
server_name ${NGINX_SERVER_NAME};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name ${NGINX_SERVER_NAME};
charset utf8;
# HSTS ヘッダー
add_header Strict-Transport-Security "max-age=${NGINX_HSTS_MAX_AGE}" always;
# `signed.crt` と `domain.key` は事前に生成し volumes で設置しておく必要があります
ssl_certificate /etc/ssl/certs/nginx/signed.crt;
ssl_certificate_key /etc/ssl/certs/nginx/domain.key;
location / {
proxy_pass ${NGINX_PROXY_PASS};
}
}
docker compose
コマンドでこれらを実際に動かすと、自己署名証明書が設定されたウェブサーバーが動くことが確認できます。
詳細に興味のある方は、実際に動かせるサンプルを GitHub に置いたのでそちらを参考にして( or 触って)みてください: