在阿里云ECS上docker安装nginx并使用acme配置SSL证书,掉进一个大坑

年初阿里云99促销的时候,买了个ECS,这几天绑定了一个域名,然后就想做个SSL证书好用 https 访问。

因为阿里云现在的证书都要收钱,免费的个人测试版的证书只有三个月有效期(下单的页面显示1年,但阿里的声明里说是3个月),而且在 ECS 上只能通过下载证书、复制到有关目录并自行修改 nginx 配置文件的方式安装,也就是说:无法自动续期。

所以决定用 acme.sh 来生成证书并实现自动续期。根据前面《在云服务器上安装Trilium打造个性化的笔记系统(3):安装SSL证书启用TLS实现https加密访问》这一篇,用 acme 工具来生成证书并开启 nginx 的SSL应该是十分轻松+愉快的,结果折腾了N个小时……

生成证书的过程比较顺利,采用的是 http 验证的方式。

中间曾经提示用 dns 验证方式,我以前也没用过这种方式,所以就试了试。dns验证有两种方式,一种用手动添加解析记录的方式可能同样无法自动续期,那肯定不能用;另一种要用到阿里云(域名是在阿里云解析的)的 appid和 appkey,试了几遍没起作用,不知道是没找对 id 和 key 还是权限没设置,也没找到设置的地方,反正阿里云的控制台我基本搞不赢,所以就回到 http 验证方式。

证书顺利生成。证书复制到 nginx 的目录下并修改配置文件以后,一直无法启用 https,浏览器提示“无法访问此页面”,排查了大半天,一直以为是用错了证书文件的问题,因为 acme 的说明里有:

所以在 cert文件、key 文件、fullchain 文件之间来回倒腾,怎么也解决不了。

最后发现是一个十分低级的错误。

阿里云有关说明里有提示,但没有结合到 docker的问题上,所以一开始没想明白,甚至把阿里云 ECS 的安全组都重新设了一遍。

最后还是在网上看一篇文章,瞬间就明白了原因:

答案就是:Docker 映射端口的时候要把 443 一起映射出去!!

证书的操作完全没有问题,问题在于,docker 建立 nginx 容器的时候,只映射了 80 端口,所以只用 http 访问的时候是没有任何错误的,但是一旦用 https,就相当于访问容器内部的 443 端口,因为没有映射,所以必然就被阻断了。

删除了 nginx 容器,重新部署,映射了 443 端口,立刻正常了。