使用Docker搭建反向代理(nginx)并支持SSL证书
首先
这篇文章是上一篇文章的续集。
在上一篇文章中,我介绍了如何在家中的Docker环境中搭建WordPress。- Qiita
新闻目录
-
- (1) Dockerとは + Dockerインストール
-
- (2) Dockerで”WordPress+Apache+PHP” + “MySQL”を立ち上げる
- ▶(3) Dockerでリバースプロキシサーバー(nginx)+SSL?<今ココ
目标读者
-
- 今までの記事を見た方
- リバースプロキシの知識が既にある方
Only one option is needed:
前提条件.
-
- SSL証明書を取得しておいてください
LetsEncryptを使用しています。
/etc/letsencryptに証明書があることを前提に進めます。
/etc/letsencrypt
├── archive
└── live # ←ここに最新の証明書が入ってます。
环境
-
- 自宅サーバー
OS: Ubuntu 20.04.2 LTS
Docker
verison: 20.10.5, build 55c4c88
Docker Compose
version: 1.28.5, build c4eb3a1
ファイルフォーマット: 3.9
这个问题 tí)
这次我们将使用Nginx来搭建反向代理服务器。
整个过程非常简单。
事前准备
请建立反向代理服务器并配置转发到各种目标服务器,同时创建Docker虚拟网络。
本次我们将连接到名为my_network的虚拟网络。
网络图
目录结构
我們在WordPress端和反向代理端分開docker-compose.yml文件。
※這並不是推薦的配置,請根據您自己的環境進行配置。
**將Compose文件合併成一個也完全沒問題。**
**實際上,不分開可能更好。**
docker-compose.yml 文件
version: "3.9"
services:
proxy:
image: nginx:latest # 2020-03-25 latest=1.19.8
volumes:
- ./templates:/etc/nginx/templates # nginxのconfファイルのテンプレート
- ./conf/certpath.txt:/etc/nginx/certpath.txt # nginxでincludeさせるSSL関係の設定
- /etc/letsencrypt:/etc/nginx/letsencrypt # Lets Encryptの署名+秘密鍵
restart: always
ports:
- "80:80"
- "443:443"
env_file:
- ./conf/conf.env
networks:
- my_network
networks:
my_network:
name: my_network
请参考这里所写的各种选项的解释。
我将解释有关模板的内容。
关于模板
Docker Hub | nginx
nginx官方镜像(ver.1.19.8)具备方便的模板功能。
我最喜欢的季节是秋天,因为天气凉爽,大自然也变得美丽多彩。透过窗户,我可以看到树叶逐渐变黄,并且漫天飞舞。秋天也是收获的季节,农田里的蔬果丰收,让人感到满足和充实。另外,秋天还有很多有趣的节日,比如中秋节和国庆节。总之,我喜欢秋天的原因是它让我感到平静、愉悦和充满希望。
使用nginx配置文件中的环境变量 (1.19版本的新功能)
原始的nginx不支持配置文件内的环境变量,但是这个镜像在nginx启动之前有一个函数可以提取环境变量。
以下是一个示例的docker-compose.yml文件。
web:
image: nginx
volumes:
– ./templates:/etc/nginx/templates
ports:
– “8080:80”
environment:
– NGINX_HOST=foobar.com
– NGINX_PORT=80默认情况下,这个函数会加载/etc/nginx/templates/*.template模板文件,并将envsubst的结果输出到/etc/nginx/conf.d。
如果放置一个引用环境变量的文件在templates/default.conf.template中,结果如下所示:
listen ${NGINX_PORT};输出结果在/etc/nginx/conf.d/default.conf文件中↓
listen 80;
简而言之,如果使用.template扩展名保存文件,它将读取环境变量,并将其转换为好看的conf.d文件。
这次我们将在./conf/conf.env文件中编写环境变量并读取它。
env_file:
- ./conf/conf.env
NGINX_HOST=example.com
NGINX_PORT=443 ssl
NGINX_WP_HOST=blog.example.com
NGINX_WP_PORT=443 ssl
模板文件如下所示。这是最简化的结构。
# HTTPをHTTPに飛ばす設定
server {
listen 80;
server_name ${NGINX_HOST};
rewrite ^(.*)$ https://$host$1 permanent;
}
############## リバースプロキシ本体 ###################
server {
listen ${NGINX_PORT};
server_name ${NGINX_HOST};
# アクセスログ 全部取る
access_log /var/log/nginx/host.access.log main;
# SSL設定
include /etc/nginx/certpath.txt;
# ロケーション設定
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
server {
listen ${NGINX_WP_PORT};
server_name ${NGINX_WP_HOST};
access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://wordpress; # コンテナ名を指定
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
中文翻译:
将wordpress.conf.template文件中的内容重述一遍。
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
抱歉,但没有这个的话,WordPress的CSS就会乱掉,所以是必要的。
对不起…我不理解设置的含义…
如果我有兴致,稍后会查一下并添加备注。
关于SSL
./conf/certpath.txtにSSLの設定を書いてます。
いずれ変わることもあるかなと思って別ファイルに書きました。
2021年3月時点ですとTLS1,TLS1.1をサポートしてるとよろしくないようなので無効にしてます。
TLS1.2の接続のみだけ許可しています。
この設定であればSSLのテストをしてくれるサイト↓で「A」は取れると思います。(TLS1.2のみだとBになる)
https://www.ssllabs.com/ssltest/
証明書をコンテナ内に配置する方法ですが、「コンテナ内で取得」か「ホストで取得してコンテナにマウント」で迷いました。Lets EncryptのイメージもDocker Hubにあるのでそれを使おうかとも思いました。
結局「ホストで取得してコンテナにマウント」で対応しています。こっちのほうが簡単そうなので。あと、コンテナ技術的にたぶん証明書はコンテナ外管理のほうがいいですよね。
ただ、Lets Encryptの最新証明書が入ってるliveフォルダって中身がarchiveフォルダへのシンボリックリンクなんですよね。liveフォルダだけをマウントさせるのは無理っぽいので/etc/letsencryptごとマウントさせてます。
証明書以外の余計なものまでマウントさせてますがまあしょうがないです…。
# SSL証明書の場所 (実際にある場所を入れてください。)
ssl_certificate /etc/nginx/letsencrypt/live/<domain_name>/fullchain.pem;
ssl_certificate_key /etc/nginx/letsencrypt/live/<domain_name>/privkey.pem;
# ssl_prefer_server_ciphersをonに指定すると、利用する暗号を選ぶ際に、
# SSLv3やTLSではサーバが示した暗号スイートが優先されます。
# offにするとクライアントのものが優先されます。デフォルトはoffです。
# これはnginxの機能というよりはOpenSSLの機能で、
# SSL_CTX_set_options()にSSL_OP_CIPHER_SERVER_PREFERENCEを設定します。
# https://heartbeats.jp/hbblog/2012/06/nginx06.html
ssl_prefer_server_ciphers on;
# サーバー側で有効にするプロトコル
ssl_protocols TLSv1.2;
# サーバー側で有効にする暗号
# 参考:https://rms.ne.jp/sslserver/basis/forward_secrecy_apache_ngix/
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
执行
只需要运行docker-compose up -d就可以了。
example.com应该会连接到nginx的默认页面,而blog.example.com应该会连接到WordPress页面。
故障排除
Nginx无法启动。
大部分情况下是由于配置文件语法错误所致,请重新检查您的设定。
もしくは、nginxは起動時にコンフィグファイルを評価し、名前解決を行います。
先にWordPressサーバーを起動しておかないと名前解決できません。先にWordPressを起動させてください。
我没有能够提出关于这个问题的具体解决方案…
也许最初的反向代理和用Compose分离其他网站的思路可能不好。
我会尝试在运营过程中不断尝试并改进构架。
被不打算的页面转到
你是否没有使用”proxy_pass https://wordpress:443″这样的描述?我之前尝试了这种方式却无法成功。当省去端口号后,才能成功连接。
最后
我终于成功使用Docker构建了网站。希望未来还能通过容器增加更多的服务。关于文件夹结构和Compose,似乎还有很多试验的余地…。
如果方便的话,请在Twitter上关注我?
Tweets by daemokra
就是这样。
请允许我参考了一个网站。 wǒ le yī gè .)
-
- linux – Letsencrypt + Docker – the best way to handle symlink? – Stack Overflow
-
- Reverse Proxy SSL証明書の集中管理 | アラコキからの Raspberry Pi 電子工作
-
- SSLに対応したNGINXリバースプロキシを構築する手順 – Qiita
-
- Let’s Encrypt で Nginx にSSLを設定する – Qiita
-
- Webサーバー nginx における SSL証明書設定の安全性向上 ~SSL Server Test で A+ 判定を目指して~ | SaintSouth.NET
- nginx連載6回目: nginxの設定、その4 – TLS/SSLの設定 – インフラエンジニアway – Powered by HEARTBEATS