SSL证书在Nginx-in-Docker上的安装

2023-04-16发布于服务部署指南 | 最后更新于2023-04-24 23:04:00

Nginx SSL 配置记录 Docker

需求背景

将本站从HTTP全面升级到HTTPS,使用的是云服务提供商的免费SSL证书。另外,此处的Nginx是作为Docker服务运行在服务器上的,需要在对应的Docker容器中进行配置修改和证书导入

也可以参考腾讯云的官方部署指南

Nginx配置

证书下载

此处以腾讯云的免费SSL证书申请为例,在申请好证书并审核通过之后,下载适用于Nginx的证书

证书下载

下载完成之后,zip压缩包中有下面几个文件

压缩包内容

需要用到的是bundle.crt.key两个文件

证书传入容器

首先需要将上述的两个文件放到服务器上,下面是将文件传入Docker的方法

  1. 先查看对应Nginx应用容器的id
sudo docker ps

容器id查看

  1. 将证书文件拷贝进容器

使用到的命令为

sudo docker cp host中的文件路径 容器id:容器中的文件路径

例如,此处将host当前文件下的两个证书拷贝到容器的根目录中

sudo docker cp ./optgeo.top_bundle.crt 2d32a:/
sudo docker cp ./optgeo.top.key 2d32a:/

在容器中进行配置

  1. 进入容器的bash
sudo docker exec -it 容器id bash
  1. 将证书文件放到/etc/nginx目录
mv optgeo.top.key /etc/nginx/
mv optgeo.top_bundle.crt /etc/nginx/
  1. 编辑配置文件

需要注意的是,容器中很可能没有安装任何文本编辑工具,需要进行额外的安装,在安装前需要先apt update一下

apt update
apt install nano

进入配置文件/etc/nginx/conf.d/default.conf进行修改,将下面这段配置加在开头。其中的server_namessl_certificatessl_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端口未映射的问题。对于一个已有的容器,要修改其端口映射,一般有两种方法:

  1. 将容器发布,再重新拉取运行时设置端口
  2. 直接修改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.jsonconfig.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端口访问