SSL证书在Nginx-in-Docker上的安装
2023-04-16发布于服务部署指南 | 最后更新于2023-04-24 23:04:00
需求背景
将本站从HTTP全面升级到HTTPS,使用的是云服务提供商的免费SSL证书。另外,此处的Nginx是作为Docker服务运行在服务器上的,需要在对应的Docker容器中进行配置修改和证书导入
也可以参考腾讯云的官方部署指南
Nginx配置
证书下载
此处以腾讯云的免费SSL证书申请为例,在申请好证书并审核通过之后,下载适用于Nginx的证书
下载完成之后,zip压缩包中有下面几个文件
需要用到的是bundle.crt
和.key
两个文件
证书传入容器
首先需要将上述的两个文件放到服务器上,下面是将文件传入Docker的方法
- 先查看对应Nginx应用容器的id
sudo docker ps
- 将证书文件拷贝进容器
使用到的命令为
sudo docker cp host中的文件路径 容器id:容器中的文件路径
例如,此处将host当前文件下的两个证书拷贝到容器的根目录中
sudo docker cp ./optgeo.top_bundle.crt 2d32a:/
sudo docker cp ./optgeo.top.key 2d32a:/
在容器中进行配置
- 进入容器的bash
sudo docker exec -it 容器id bash
- 将证书文件放到
/etc/nginx
目录
mv optgeo.top.key /etc/nginx/
mv optgeo.top_bundle.crt /etc/nginx/
- 编辑配置文件
需要注意的是,容器中很可能没有安装任何文本编辑工具,需要进行额外的安装,在安装前需要先apt update
一下
apt update
apt install nano
进入配置文件/etc/nginx/conf.d/default.conf
进行修改,将下面这段配置加在开头。其中的server_name
、ssl_certificate
与ssl_certificate_key
字段需要根据实际域名修改。另外,location /
字段按照实际情况设置(和原来已有的HTTP设置相同即可)。
server {
listen 443 ssl;
server_name www.optgeo.top;
ssl_certificate optgeo.top_bundle.crt;
ssl_certificate_key optgeo.top.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 / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
修改保存后,使用下面的命令检查Nginx配置文件是否语法正确
nginx -t
若语法正确,会出现“synax is ok”的字样
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
再执行下面的命令重载Nginx即可
nginx -s reload
此时还是无法通过https://你的域名访问,原因在于Nginx容器目前只对外映射了80段口,并没有映射443端口,这个问题在后面会进行解决
配置自动跳转
若只进行上面的配置,在使用http://你的域名访问时,浏览器仍然会显示“不安全”。我们希望在通过80端口访问时,也会跳转到https的安全访问
此处采用301永久重定向进行实现。在原先监听80端口的server
块中进行修改。同样修改配置文件/etc/nginx/conf.d/default.conf
,将监听80端口的server
块中的location去掉,加上return 301 https://$host$request_uri;
修改完后,配置文件/etc/nginx/conf.d/default.conf
大概长下面这样
server {
listen 443 ssl;
server_name www.optgeo.top;
ssl_certificate optgeo.top_bundle.crt;
ssl_certificate_key optgeo.top.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 / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
server {
listen 80;
listen [::]:80;
server_name www.optgeo.top;
return 301 https://$host$request_uri;
}
Docker配置
接下来就要解决容器443端口未映射的问题。对于一个已有的容器,要修改其端口映射,一般有两种方法:
- 将容器发布,再重新拉取运行时设置端口
- 直接修改Docker的容器文件
第二种方法较为简单,此处采用这种方法来修改端口映射。Docker的容器文件在/var/lib/docker/containers
下,该命令需要超级管理员才能进入操作
查看容器完整id
为了防止改错文件,先使用下面的命令查看容器的完整id
sudo docker inspect id简写 | grep Id
关闭Docker并进入容器对应的文件夹
在对容器文件进行修改前,需要先关闭容器,并停止Docker服务
sudo docker stop id简写
sudo systemctl stop docker
需要先使用su
切换为超级管理员,若之前并没有使用超级管理员身份做过操作,首次切换需要使用sudo passwd
设置超级管理员的密码
su
cd /var/lib/docker/containers/容器完整id/
修改容器文件
需要修改hostconfig.json
和config.v2.json
两个文件
把hostconfig.json
中的
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"80"}]}
改为
"PortBindings":{"443/tcp":[{"HostIp":"","HostPort":"443"}],"80/tcp":[{"HostIp":"","HostPort":"80"}]}
把config.v2.json
中的
"ExposedPorts":{"80/tcp":{}}
改为
"ExposedPorts":{"443/tcp":{},"80/tcp":{}}
重启Docker服务与容器
sudo systemctl start docker
sudo docker start id简写
此时使用sudo docker ps
可以看到443端口已经成功映射绑定。就可以使用https访问网站了
若此时仍无法访问,请查看: 1. 实例在云服务提供商处的防火墙是否开启了443端口 2. 云服务器的ufw防火墙是否允许443端口访问