在Docker环境中获取Let’s Encrypt的SSL证书
首先
-
- この記事では、dockerのnginxコンテナを使ったwebサイトのhttps化手順をまとめています。
-
- dockerコンテナと、let’s encryptを使ってサイトのhttps化を目指している方の参考になれば幸いです。
- また、自身の知識の整理のためにssl証明書について冒頭でまとめていますが、既にご存じの方は3. ssl証明書の取得手順までスキップしてください。(もし知識の浅い部分があればご指南いただけると嬉しいです。)
我在开发环境中的工作
-
- サーバ: ubuntu 20.04
- nginx (docker)
中文目录
1. SSL证书的目的
2. 关于Let’s Encrypt
3. SSL证书的获取步骤
4. SSL证书的更新方法
5. 总结
1. SSL证书的目标是什么?
-
- 結論から言うと、ssl証明書の目的は webサイトの通信を暗号化してセキュリティを高めることです。
-
- 暗号化されていないhttp通信では、平文のままサーバ間でやりとりをするため通信が傍受されてしまった場合、情報を悪用されるリスクがあります。
- 一方でssl通信は、通信の内容が暗号化されているため傍受された場合でも、傍受者はその通信内容を悪用することができません。
SSL证书的类型
-
- webサイトでssl通信をするために必要な ssl証明書 は無料のものから十数万するものまであります。
-
- ただ、無料だからといって、通信の暗号化の機能が劣っているということではないそうです。
-
- では、なぜ有料のssl証明書があるかというと、サイト運営者の身分証明 のためです。
- ssl証明書には大まかに下記の3種類があります。
-
- 価格が高くなるにつれて、提示する個人情報が詳細になっていきます。
-
- 個人情報が詳細になるほどwebサイトのセキュリティ(信頼性)としては高いと言えます。
-
- これまで説明したように、ssl証明書は無料でメールアドレスの確認だけで作れてしまうものもあります。
サイトの運用者が悪者だった場合は、いくらssl通信で暗号化されているからといって安全とは言えません。
もし、これが組織がお金を払い、身分情報を提示して発行したssl証明書であれば、サイトの信頼性は高く安全と言えると思います。
2. 关于Let’s Encrypt
-
- これまで 有料のssl証明書の役割について説明してきましたが、個人のwebサイトを試しに立ち上げてみたい、というような方であれば最低限のssl通信を実現できるssl証明書があれば十分だと思います。
-
- 無料のssl証明書 としてlet’s encrypt が有名どころとしてあります。
この記事を作るにあたり他の無料ssl証明書も調べたところ zerossl というサービスもあるようです。全てブラウザで完結するとのことなので lets encrypt よりも簡単かもしれないです。
詳しい内容は下記の記事でまとめられていたので興味を感じられた方をご覧ください。
我试用了ZeroSSL这个可以获得免费SSL证书的服务。
- この記事では let’s encryptを使ってwebサイトにssl証明書を適用する方法を紹介していきます。
3. 获得SSL证书的步骤
在 Docker 环境下,无法参考 Let’s Encrypt 的官方指南。
-
- let’s encrypt 公式のgetting started を見ます。
https://letsencrypt.org/ja/getting-started/
公式によると、certbotというサービスを使うことで簡単に証明書の取得ができるようです。
certbotのページを開くと、各環境に合ったcertbotのインストール手順を紹介してくれます
ただ、今回の環境は dockerのnginxコンテナで動いているため該当する選択肢はないように見えました。
获取Certbot的Docker镜像。
-
- 情報を探すと、公式が出しているcertbotのコンテナイメージがありました。
https://hub.docker.com/r/certbot/certbot/
こちらのイメージを使い、Dockerfileとdocker-compose.ymlを作成します
筆者はこのような構成でディレクトリを作成しました。
.
└── nginx_docker
├── Dockerfile ... nginx用
├── certbot
│ └── Dockerfile ... certbot用
├── conf.d
│ ├── default.conf ...初めてssl証明書を取得するまで使うnginx設定ファイル
│ └── ssl_server.conf.txt ...ssl証明書の取得後、使うnginx設定ファイル
├── dist ... nginxでこちらのディレクトリの資材へルーティングします
│ └── index.html
└── docker-compose.yml
接下来,我们将准备各种设置文件。
创建certbot和nginx的Dockerfile。
certbotとnginxのDockerfileの中身です
certbot
# base image
FROM certbot/certbot:latest
- nginx
# base image
FROM nginx:latest
WORKDIR /dist
RUN nginx -t
RUN service nginx restart
2. 在 docker-compose.yml 文件中添加 certbot 插件。
由於有人指出記錄不完整,因此我們進行了部分更新。
version: "3"
services:
nginx:
image: nginx:latest
# nginxをリスタートした時にコンテナが終了しないようにする
restart: always ... certbotで証明書を取得した後、nginxをリスタートします。こちらを入れないとリスタートでコンテナが落ちるので追加します。
container_name: nginx
build:
context: .
dockerfile: ./Dockerfile
ports:
- "80:80"
- "443:443" # コンテナへhttps通信が通るようにport解放します
# 20日おきにnginxを再読み込みする
command: "/bin/sh -c 'while :; do sleep 20d & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
volumes:
# nginxの設定ファイル
- ./conf.d:/etc/nginx/conf.d
# nginxのルートパス
- ./dist:/dist
- /etc/letsencrypt:/etc/letsencrypt #ssl証明書が配置されるパス
certbot:
image: certbot/certbot:latest
container_name: certbot
build:
context: .
dockerfile: ./certbot/Dockerfile
# 10日おきに証明書を更新する(期限切れまで30日以上あれば更新しない)
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 10d & wait $${!}; done;'"
volumes:
- /etc/letsencrypt:/etc/letsencrypt #こちらに取得したssl証明書が配置されます。nginxコンテナでも同じくマウントして共有します。
- ./dist:/dist
command: ["--version"]
-
- 補足したい部分についてはコメントを追記しています。
証明書を取得すると/etc/letsencryptに配置されます。これはnginxコンテナでも使いたいので同じパスをマウントします。
nginxコンテナでrestart: alwaysしておくと、コンテナ外からnginxのリロードをしてもコンテナが落ちなくなるのでつけておくと良いです
创建nginx的配置文件。
nginx設定ファイルは初回のssl証明書取得前後で、2つ使い分けます
まずは初めてssl証明書を取得するまで使う設定ファイルdefault.conf
server {
listen 80;
server_name {ドメイン名}; # ★適宜変更してください
location / {
root /dist/;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
-
- 次に、ssl証明書取得後に使う設定ファイルです。ssl_server.conf.txt
使うときは、.txtの拡張子を外します。
server {
server_name {ドメイン名}; # ★ドメイン名を適宜変えてください
listen 80;
listen [::]:80;
# 証明書更新のために:80/.well-knownにアクセスしたいので、ここだけリダイレクトはしない
location ^~ /.well-known {
root /dist/;
}
# 全てのリクエストをSSLサイトにリダイレクト
location / {
return 301 https://$host$request_uri;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
server_name {ドメイン名}; # ★ドメイン名を適宜変えてください
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/{ドメイン名}/fullchain.pem; # ★ドメイン名を適宜変えてください
ssl_certificate_key /etc/letsencrypt/live/{ドメイン名}/privkey.pem; # ★ドメイン名を適宜変えてください
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers '{任意のアルゴリズム}'; ★適宜変えてください。ssl_ciphers自体を省略でも動作するようです。
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=2592000" always;
location / {
root /dist/;
index index.html index.htm;
}
}
-
- 80ポートに来た通信は全て、443ポートのhttps通信にリダイレクトされるようにしています。
-
- 2つの設定ファイルを使い分ける理由
certbotは初めて証明書を取得するときに、80ポートで通信します。そのため、ssl_server.conf.txtで設定されているように、443ポートにリダイレクトされると失敗します。初回は.well-knownディレクトリも使われないです。
根据配置文件来启动容器。
-
- docker-compose.ymlのあるパスまで移動して、下記コマンドを実行します。(コンテナイメージの取得)
docker compose build
dockerコンテナを立ち上げます
docker compose up -d nginx
この時点だと、まだssl証明書が入っていないので、サイトは閲覧できないはずです
certbotコンテナを実行して、ssl証明書を取得します。
docker compose run –rm certbot certonly –webroot -w {nginxのドキュメントルート} -d {ドメイン名}
{nginxのドキュメントルート}は設定ファイルのままであれば、/distになります
{ドメイン名}は適宜変更してください
これで、etc/letsencrypt配下に証明書が配置されているはずです
これで、ssl証明書を使う準備が整ったので、nginx.confをssl_server.conf.txtに差し替えます。
ssl_server.conf.txtの.txt拡張子を外します。
default.confに拡張子.txtを追加します。(.conf拡張子が外れるとnginxで適用されなくなります)
そしてdocker compose exec nginx nginx -s reloadを実行してnginxをリロードします
以上で、httpsで通信できれば作業は完了です。
2023/7/9更新:由于上述default.conf文件中第8行附近的内容存在拼写错误,已进行修正。
位置 ^~ /.well-known {
[错误] root /dsit/;
[修正] root /dist/;
4. SSL证书更新的步骤
let’s encrypt の証明書は90日で期限が切れてしまうために定期的に更新が必要です。
ただ、今回紹介したssl_server.confの設定であれば、docker-compose.ymlで設定したentrypointが働き、定期的に証明書を取り直してくれるため、基本的には更新作業は不要です。
証明書の自動更新方法については下記の記事を参考にさせていただきました。
使用 Docker Nginx 和 Let’s Encrypt 实现自动更新功能(无需使用 cron)。
- ※[注意] 自動更新が動作確認については本記事ではまだ確認できていないため、すぐに動作確認したい方は上記の記事をご覧ください。(時間が経過して動作確認がとれたら記事を更新する予定です)
5. 最后
-
- 作業を振り返って、dockerを使った let’s encrypt証明書の発行も意外と簡単でした。
公式からdockerイメージが出されているのが大きかったです。
一方で、Dockerfileや、docker-compose.ymlのノウハウがあれば、自動更新周りをもう少し見通しよく作れそうだと感じたので、個人的には証明書更新よりもdocker難しいという感想を持ちました。
ssl証明書の作成を通じて、webサイトのセキュリティについても興味を持ち始めたので、今後はそちらについても記事発信していきたいです。