Docker Compose で NGINX の起動前に自己署名証明書を生成する方法

Docker

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_onservice_completed_successfully という condition を使えば比較的シンプルでかんたんに実現できるので今回はこの方法を説明します。

depends_on に興味のある方には以下のページなども参考になるかと思います:

以下やり方です。

  • 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 触って)みてください:


アバター
後藤隼人 ( ごとうはやと )

Python や PHP を使ってソフトウェア開発やウェブ制作をしています。詳しくはこちら