ACME.sh 也算是把证书签发这件小事做得相当完善,但他们的文档不是很好查,每次部署都得确认一些细节,因此做个备忘。
Nginx 部分没有什么好说:
services:
nginx:
image: nginx:alpine
container_name: nginx
restart: always
depends_on:
- xxx #我习惯放在 Web 应用后面启动
volumes:
- ~/nginx/conf.d:/etc/nginx/conf.d #自定义用,如果只是 https 甚至都可以不需要
- ~/nginx/logs:/var/log/nginx #收集日志还是有必要的
- ~/nginx/ssl:/etc/nginx/ssl #一探究竟用,其实用不着
ports:
- "443:443"
- "80:80"
labels:
- "sh.acme.autoload.domain=example.com" #重要,acme.sh 靠这个来定位 Nginx 的容器
重点是 ACME.sh 的部分:
services:
#前提是 nginx 的 labels 得在
acme.sh:
image: neilpang/acme.sh
container_name: acme.sh
command: daemon
volumes:
- ./acmeout:/acme.sh
- /var/run/docker.sock:/var/run/docker.sock
environment:
#部署到 Nginx 容器用,纯纯复制粘贴就行
- DEPLOY_DOCKER_CONTAINER_LABEL=sh.acme.autoload.domain=example.com
- DEPLOY_DOCKER_CONTAINER_KEY_FILE=/etc/nginx/ssl/example.com/key.pem
- DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/ssl/example.com/cert.pem"
- DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/ssl/example.com/ca.pem"
- DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/ssl/example.com/full.pem"
- DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
都运行起来后回到宿主机,用 ACME.sh 容器运行它的脚本。都可以用,这里用 CloudFlare API 签发举例:
docker exec \
-e [email protected] \
-e CF_Key=xxxxxxxxxx \
acme.sh --issue -d example.com --dns dns_cf \
--server letsencrypt
最后一个参数是因为 ACME.sh 默认已经换成了 ZeroSSL,可能有技术考虑,但更多应该是赞助。如果要继续用 Let's Encrypt,得额外指定一下。
证书成功签发后,可以自动或手动部署到 Nginx 去:
docker exec acme.sh --deploy -d example.com --deploy-hook docker
几条 docker 命令的 -e
参数都可以和 compose 文件里的环境变量相互替换,我觉得自用的话可能一股脑全扔进 compose 文件(敏感字段放在同目录的 .env 文件并且记得在 Git 里忽略)比较合适,这里就不写得那么花哨了。
然后 ACME.sh 就已经帮你做完了所有事,包括监听 443 端口、部署证书和重载 Nginx 配置。也就是说,你就算是个崭新的 Nginx 容器,没有配置任何站点,到这里也可以直接使用 https 访问刚才签发的域名了。
其实操作上官方文档说得非常清楚,但对具体做了什么少了点描述,希望这是一个还算有用的补充。