毎回 OpenSSL コマンドを調べていませんか?
開発環境でもHTTPSが必要になるケース
最近のWebアプリケーション開発では、以下のような理由で開発環境でもHTTPSが必要になることが増えています:
- ブラウザーAPIの制約: Service Worker や Web Cryptography API など、HTTPS 環境でしか動作しない API が増加
- 本番環境との一致: 本番環境が HTTPS の場合、開発環境も同じにしないと挙動が変わる
- 外部サービス連携: OAuth、Webhook 受信など HTTPS が必須の場合が多い
- データベースSSL接続: MySQL 9.0 以降では SSL 接続がデフォルトで必須になるなど、データベースの SSL 化が進んでいる
OpenSSLコマンドでの証明書生成の課題
開発環境でHTTPS化するには自己署名SSL証明書が必要ですが、OpenSSL のコマンドは複雑です:
- 何度調べても覚えられない
- ワイルドカード証明書の作り方が毎回わからない
- チーム内で証明書の作り方がバラバラ
解決策
ワイルドカード自己署名 SSL 証明書を生成する Docker イメージを作成しました:
futureys/ssl-certificate - Docker Image
この Docker イメージを使えば、環境変数を指定するだけで
標準的な自己署名 SSL 証明書が生成できます
さらに、Docker Compose と組み合わせることで、
開発環境のセットアップを完全に自動化できます
このイメージを使うメリット
✅ OpenSSL コマンドを覚える必要なし - 環境変数だけで設定完了
✅ チーム全体で統一 - Dockerfile や compose.yml で共有可能
✅ 自動化が簡単 - CI/CD や Docker Compose に組み込める
✅ 標準的なディレクトリ構成 - Linux 標準の /etc/pki を使用
ユースケース
このツールは以下のようなシーンで活用できます:
- ローカル開発環境: HTTPS 接続が必要なアプリケーションの開発
- テスト環境: SSL/TLS 接続のテスト
- マイクロサービス間通信: コンテナ間のセキュアな通信
- データベース接続: MySQL や PostgreSQL などの SSL 接続
クイックスタート
最も簡単に試せる例です:
services:
ssl-certificate:
environment:
DOMAIN_NAME: localhost
SUPPORT_ROOT_DOMAIN: true
image: futureys/ssl-certificate:latest
volumes:
- pki:/etc/pki
web:
command:
- sh
- -c
- |
echo 'server {
listen 443 ssl;
ssl_certificate /etc/pki/tls/certs/servercert-localhost.pem;
ssl_certificate_key /etc/pki/tls/private/serverkey-localhost.pem;
location / { return 200 "SSL is working!\n"; add_header Content-Type text/plain; }
}' > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'
depends_on:
ssl-certificate:
condition: service_completed_successfully
image: nginx:alpine
ports:
- "443:443"
volumes:
- pki:/etc/pki:ro
volumes:
pki:
起動後、https://localhost にアクセスすると "SSL is working!" が表示されます
この時点ではブラウザーに「信頼されていない証明書」の警告が表示されますが、次の手順で CA 証明書を取り出し、ブラウザーにインストールすることで回避できます:
docker compose cp web:/etc/pki/CA/cacert-localhost.pem ./cacert-localhost.pem
証明書のインストール手順については
後述の「CA 証明書のブラウザーへのインストール」セクションも参照してください
生成されるファイル
CA (認証局) 証明書とサーバー証明書の両方を、
関連する秘密鍵や証明書要求ファイルとともに生成します
6 つのファイルが生成されます:
CA (認証局) 関連
-
CA 秘密鍵:
/etc/pki/CA/private/cakey.pem -
CA 証明書要求:
/etc/pki/CA/cacert-<ドメイン名>.csr -
CA 証明書:
/etc/pki/CA/cacert-<ドメイン名>.pem← ブラウザーにインストールするファイル
サーバー証明書関連
-
サーバー秘密鍵:
/etc/pki/tls/private/serverkey-<ドメイン名>.pem -
サーバー証明書要求:
/etc/pki/tls/certs/servercert-<ドメイン名>.csr -
サーバー証明書:
/etc/pki/tls/certs/servercert-<ドメイン名>.pem← サーバーで使用
基本的な使い方
ボリュームマウントと環境変数を指定してイメージを実行します:
docker run --env DOMAIN_NAME=exampledomain.com \
-v $(pwd)/CA:/etc/pki/CA \
-v $(pwd)/tls/certs:/etc/pki/tls/certs \
-v $(pwd)/tls/private:/etc/pki/tls/private \
futureys/ssl-certificate
このコマンドを実行すると、exampledomain.com 用の証明書が
現在のディレクトリの CA、tls/certs、tls/privateディレクトリに生成されます
Docker Composeとの統合
Docker Compose を使用すると、アプリケーション起動時に自動的に証明書を生成できます
MySQL データベース接続を保護する例を紹介します
1. compose.yml の準備
services:
ssl-certificate:
environment:
DOMAIN_NAME: database
SUPPORT_ROOT_DOMAIN: true
image: futureys/ssl-certificate:latest
volumes:
- pki:/etc/pki
database:
command:
- --ssl-ca=/etc/pki/CA/cacert-database.pem
- --ssl-cert=/etc/pki/tls/certs/servercert-database.pem
- --ssl-key=/etc/pki/tls/private/serverkey-database.pem
depends_on:
ssl-certificate:
condition: service_completed_successfully
entrypoint: setup-certificate.sh
environment:
MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD}
healthcheck:
test:
- CMD
- mysqladmin
- ping
- -h
- localhost
- -u
- root
- -pexamplepass
- --ssl-mode=REQUIRED
interval: 5s
timeout: 10s
retries: 5
start_period: 30s
image: mysql:9.5.0
volumes:
- pki:/etc/pki
- ./setup-certificate.sh:/usr/local/bin/setup-certificate.sh
# MySQL 9.0.0 未満の場合は以下も必要
- ./mysql_conf.d:/etc/mysql/conf.d
volumes:
pki:
2. MySQL 9.0.0 未満の場合の設定
MySQL 9.0.0 未満を使用する場合は次のファイルを作成します:
[mysqld]
# SSL 接続を強制
require_secure_transport = ON
3. setup-certificate.sh の準備
証明書のパーミッション設定と MySQL の起動を行うスクリプトを作成します:
#!/bin/bash
set -eu
SERVERKEY="/etc/pki/tls/private/serverkey-database.pem"
chown root:mysql "${SERVERKEY}"
chmod 640 "${SERVERKEY}"
# docker-entrypoint.sh は公式データベースイメージのデフォルト ENTRYPOINT
exec docker-entrypoint.sh "$@"
重要: スクリプトに実行権限を付与してください:
chmod +x setup-certificate.sh
4. 起動
以下のコマンドで SSL が有効化された MySQL が起動します:
docker compose up
内部的には、次の手順が自動的に行われます:
- サービス:
ssl-certificateが証明書を生成 - サービス:
databaseは証明書生成の完了を待機 -
setup-certificate.shが証明書のパーミッションを適切に設定 - MySQL が生成された証明書を使用して SSL 接続を有効化
起動時にパラメーターとして与える環境変数
DOMAIN_NAME
証明書を生成するドメイン名を指定します
この環境変数は必須です
例:
DOMAIN_NAME=exampledomain.com
上記の場合、*.exampledomain.comのすべてのサブドメインで使用できます
(ワイルドカード証明書が生成されるため)
SUPPORT_ROOT_DOMAIN
ルートドメインのカバレッジをサブドメインと一緒に有効にするブール値フラグです
trueに設定すると、ルートドメインも証明書に含まれます
デフォルトはfalseです
例:
SUPPORT_ROOT_DOMAIN=true
例えば、DOMAIN_NAME=exampledomain.comの場合:
| SUPPORT_ROOT_DOMAIN | 対象となるドメイン | 説明と例 |
|---|---|---|
false(デフォルト) |
*.exampledomain.comのみ |
api.exampledomain.com、www.exampledomain.comなど |
true |
exampledomain.comと*.exampledomain.comの両方 |
ルートドメインexampledomain.comも含む |
CA 証明書のブラウザーへのインストール
自己署名証明書をブラウザーからアクセスする Web サーバーで使用する場合、
CA 証明書をブラウザーにインストールする必要があります
(ブラウザーでの「信頼されていない証明書」の警告を防ぐため)
- コンテナから生成された CA 証明書 (
cacert-<ドメイン名>.pem) を取得 - ブラウザーの設定画面を開く
- 証明書管理セクションに移動
- CA 証明書としてインポート・信頼
1. CA 証明書ファイルをコンテナから取り出す
docker compose cp web:/etc/pki/CA/cacert-<ドメイン名>.pem ./cacert-<ドメイン名>.pem
例: DOMAIN_NAME=exampledomain.com の場合:
docker compose cp web:/etc/pki/CA/cacert-exampledomain.com.pem ./cacert-exampledomain.com.pem
2. Chrome への証明書インストール手順
- Chrome の設定を開く (
chrome://settings) - 「プライバシーとセキュリティ」→「セキュリティ」を選択
- 「証明書の管理」をクリック
以降は OS ごとに異なります
Mac の場合
- 「Mac からインポートした証明書を管理する」をクリック
- 「キーチェーンアクセスを開く」をクリック
- 名前とパスワードの入力を求められたら、このコンピュータの管理者ユーザの名前とパスワードを入力します
- 「システムキーチェーン」の「システム」をクリック
- 証明書ファイルをキーチェーンアクセスアプリ上にドラッグします
- 名前とパスワードの入力を求められたら、このコンピュータの管理者ユーザの名前とパスワードを入力します
- インポートした証明書をダブルクリック
- 「信頼」セクションを展開
- 「この証明書を使用する際:」のドロップダウンメニューで「常に信頼」を選択
- ウィンドウを閉じて、名前とパスワードの入力を求められたら、このコンピュータの管理者ユーザの名前とパスワードを入力します
参考: Mac でキーチェーンアクセスを使用してキーチェーンに証明書を追加する - Apple サポート (日本)
Windows の場合
- 「Windows からインポートした証明書を管理する」をクリック
- 「認証局」タブを選択
- 「インポート」をクリック
- ダウンロードした
cacert-localhost.pemを選択 - 「この証明書を使って Web サイトを識別する際に信頼する」にチェック
- 「OK」をクリック
参考: How do I deal with NET:ERR_CERT_AUTHORITY_INVALID in Chrome?
3. ドメイン名が localhost でない場合の hosts ファイル設定
ドメイン名を localhost 以外に設定した場合、hosts ファイルに設定を追加する必要があります
例: DOMAIN_NAME=exampledomain.com の場合:
127.0.0.1 local.exampledomain.com
-
Windows:
C:\Windows\System32\drivers\etc\hosts -
Mac/Linux:
/etc/hosts
トラブルシューティング
「Permission denied」エラーが出る
setup-certificate.sh に実行権限がない可能性があります:
chmod +x setup-certificate.sh
ブラウザーで「信頼されていない」と表示される
以下の原因が考えられます:
原因1: CA 証明書がブラウザーにインストールされていない
CA 証明書 (cacert-<ドメイン名>.pem) をブラウザーにインストールしてください
詳細は前述の「CA 証明書のブラウザーへのインストール」セクションを参照してください
原因2: アクセスしているドメイン名と証明書のドメイン名が一致していない
ドメイン名を localhost 以外に設定しているのに
https://localhost にアクセスしていませんか?
ブラウザーからアクセスする際は
DOMAIN_NAME で指定したドメイン名(またはそのサブドメイン)を使用する必要があります
確認方法
- Docker Compose の環境変数
DOMAIN_NAMEの値を確認 - ブラウザーでアクセスしている URL のドメイン名が
DOMAIN_NAMEの値(またはそのサブドメイン)と一致しているか確認
対処法
-
DOMAIN_NAMEで指定したドメイン名でアクセス- 例:
DOMAIN_NAME=exampledomain.comの場合、
https://local.exampledomain.comにアクセス
- 例:
- Hosts ファイルで特定のドメイン名をローカル IP アドレスにマッピング
- 「CA 証明書のブラウザーへのインストール」の
「3. ドメイン名が localhost でない場合の hosts ファイル設定」を参照
- 「CA 証明書のブラウザーへのインストール」の
証明書が生成されない
ボリュームマウントのパスが正しいか確認してください
docker runの場合は$(pwd)、Docker Composeの場合は
相対パスまたは名前付きボリュームを使用します
参考資料
詳細な使い方やソースコードは GitHub リポジトリをご覧ください: