在容器里使用 acme.sh
之前尝试了以最小系统权限运行证书签发脚本,上面用到的服务器在香港特区,所以下载和更新脚本软件都很快,但换用内地的服务器就无法更新软件。好在有 Docker Hub 镜像网站的存在,直接拉取容器镜像部署就完事了,顺便就探索了下用容器化的办法来安装 acme.sh,并且更新证书到容器的宿主机上的方法。
主要的问题
问题的起因是 GitHub 在内地连接不通畅导致 acme.sh 的联网式安装无法进行。我想到一个简单的解决方法是做容器化部署,既能使用腾讯云的 Docker Hub 镜像加速下载,又能隔离软件和宿主系统的运行环境,一石二鸟。😎
正因为容器和宿主环境的隔离,而 Nginx 大多数情况是要在容器的宿主系统上运行,此时 acme.sh 自带的钩子程序就无法重启 Nginx 来载入新证书。如果这个问题处理不得当,就会导致证书没有真正被更新到 Nginx。我的解决办法是写一个可已检查证书是否更新的计划任务,每天自动运行一次,如果证书更新了就重启 Nginx。
我的实践
首先是启动守护程序。如果使用了 DNS 验证模式,还要在容器环境中导入 API Token(以下 --env 以 CloudFlare API 举例)
1 | docker run --restart always -itd \ |
之后创建一个 acme.sh 容器指令的精简别名,使用命令申请和安装证书。
1 | # 创建别名 |
最后,写一个脚本放到宿主系统,用于检查证书是否更新、证书完整性和重启 Nginx。
1 | file="/path/to/acme.sh/out/reload" |
在容器的宿主机上用计划任务执行上面的脚本。使用 crontab -e 打开任务编辑器,写入:
1 | 33 0 * * * /path/to/acme.sh/out/reload.sh |
总结
哪怕是脚本程序也用容器运行,这样不仅隔离了宿主系统和各种应用服务,降低了系统环境的复杂性,减少了耦合度,也提高了安全性。🤪