现在有 docker 容器运行的两个 web 应用,两个域名,我希望只用80端口访问这两个web站点,其中一个要部署SSL。下面将通过 nginx 反向代理来实现。
操作环境:
主机:单台主机,一个公网ip
相关容器
nginxproxy 用作nginx反向代理 (版本:nginx/1.23.1)(镜像:nginx:alpine)
jenkins 站点1
nginx-oulh 站点2
docker network 设定
给各个容器分配同一个网络,并且设置别名分别为nginxproxy、jenkins、nginx-oulh,可以直接使用别名来互相通信,也避免ip地址变动带来的麻烦
[leo@CentOS7 ~]$docker network create webservice
b099067fea347f8f710e0c4cc10ad1e63fc65694e46b714557f8cd0336453fef
[leo@CentOS7 ~]$
[leo@CentOS7 ~]$docker network connect --alias nginxproxy webservice nginxproxy
[leo@CentOS7 ~]$docker network connect --alias jenkins webservice jenkins
[leo@CentOS7 ~]$docker network connect --alias nginx-oulh webservice nginx-oulh
各容器ip端口映射:
[leo@CentOS7 ~]$docker ps -f network=webservice
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f0f9a0086f oulh/nginxproxy:alpine "/docker-entrypoint.…" 21 hours ago Up 17 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginxproxy
734a00cb48a0 nginx:alpine "/docker-entrypoint.…" 26 hours ago Up 26 hours 0.0.0.0:7788->80/tcp nginx-oulh
cac54b64a4cf jenkinsci/blueocean "/sbin/tini -- /usr/…" 2 days ago Up 40 hours 0.0.0.0:8080->8080/tcp, 50000/tcp jenkins
nginx 代理配置
被代理站点的配置不用改动,只需在 nginxproxy 容器中对两个站点进行代理设置就行了。
创建两个conf文件
[leo@CentOS7 ~]$docker exec -it nginxproxy sh
/ # cp /etc/nginx/conf.d/default.conf jenkins.conf
/ # cp /etc/nginx/conf.d/default.conf nginx-oulh.conf
jenkins.conf
注意,这里因为 jenkins 服务监听的是8080端口,所以要加上8080端口
# jenkins.conf
server {
listen 80;
listen [::]:80;
server_name jks.oulh.ml;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://jenkins:8080;
# proxy_pass http://172.17.0.3:8080;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
nginx-oulh.conf (不带SSL)
# nginx-oulh.conf
server {
listen 80;
listen [::]:80;
server_name www.oulh.ml;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://nginx-oulh;
# proxy_pass http://172.17.0.4;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
配置文件更改完后记得重载 nginx 服务 : nginx -s reload
反向代理部署 SSL
在代理服务器上部署就行了,因为浏览器不知道、更不用理会代理服务器和站点服务器之间的通信。
要么在代理服务器(nginxproxy 容器)上部署,要么两台服务器都部署,不能只在站点服务器(nginx-oulh 容器)上部署。
把 oulh.ml 站点的SSL证书相关文件下载到代理服务器上,主要是 .crt 和 .key 两个文件。
# nginx-oulh.conf
server {
listen 443 ssl;
listen 80;
# 绑定证书的域名
server_name www.oulh.ml;
# 证书文件的相对路径或绝对路径
ssl_certificate conf.d/sslcrt/oulh.ml_bundle.crt;
# 私钥文件的相对路径或绝对路径
ssl_certificate_key conf.d/sslcrt/oulh.ml.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://nginx-oulh;
# proxy_pass http://172.17.0.4;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
小坑:我把ssl文件放在了 /etc/nginx/conf.d/sslcrt 目录下,nginx-oulh.conf 文件位于/etc/nginx/conf.d/ ,但它似乎以 /etc/nginx 为根目录,当我填写相对路径 sslcrt/oulh.ml_bundle.crt 的时候会报错
/etc/nginx/conf.d # nginx -t
2022/08/26 11:33:34 [emerg] 79#79: cannot load certificate "/etc/nginx/sslcrt/oulh.ml_bundle.crt": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/sslcrt/oulh.ml_bundle.crt','r') error:2006D080:BIO routines:BIO_new_file:no such file)
nginx: [emerg] cannot load certificate "/etc/nginx/sslcrt/oulh.ml_bundle.crt": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/sslcrt/oulh.ml_bundle.crt','r') error:2006D080:BIO routines:BIO_new_file:no such file)
nginx: configuration file /etc/nginx/nginx.conf test faile
HTTP 自动跳转 HTTPS
将 HTTP 请求自动重定向到 HTTPS,可以通过以下操作设置:
- 在页面中添加 JS 脚本。
- 在后端程序中添加重定向。
- 通过 Web 服务器实现跳转。
- Nginx 支持 rewrite 功能。若您在编译时没有去掉 pcre,您可在 HTTP 的 server 中增加
return 301 https://$host$request_uri;
,即可将默认80端口的请求重定向为 HTTPS
# nginx-oulh.conf
server {
listen 80;
server_name www.oulh.ml;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
# listen 80;
# 绑定证书的域名
server_name www.oulh.ml;
# 证书文件的相对路径或绝对路径
ssl_certificate conf.d/sslcrt/oulh.ml_bundle.crt;
# 私钥文件的相对路径或绝对路径
ssl_certificate_key conf.d/sslcrt/oulh.ml.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://nginx-oulh;
# proxy_pass http://172.17.0.4;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
参考:
SSL 证书 国际标准 SSL 证书安装-证书安装-文档中心-腾讯云 (tencent.com)
nginx 官方文档: