acme.sh 自动解析、申请并续签免费泛域名证书(Docker容器部署+腾讯云DNSPod)
本文介绍如何通过Docker容器一键部署acme.sh客户端,实现基于腾讯云DNSPod解析的免费泛域名证书自动申请、自动续签,全程实操可直接复用,核心代码保持不变,适配nginx等Web服务的证书部署需求。
ACME(自动证书管理环境)是由互联网工程任务组(IETF)维护的行业标准协议,用于自动化Web服务器SSL/TLS证书的部署流程;acme.sh是一款广泛应用的ACME协议客户端,支持SSL证书的自动申请、自动续签及批量管理,无需人工干预即可维持证书有效性。
前置准备
-
腾讯云SecretId与SecretKey:用于授权acme.sh调用腾讯云DNSPod接口完成DNS解析验证,获取方式参考官方文档:https://cloud.tencent.com/document/product/302/105900
-
环境说明:本次部署基于Docker容器,需提前安装Docker及Docker Compose;目标服务器需开放相关网络权限,确保能正常访问ACME服务器(如ZeroSSL)及腾讯云API接口。
-
证书路径说明:以nginx服务为例,本文指定
/etc/nginx/ssl作为本地应用证书挂载路径,用于存放最终部署的证书文件,可根据实际服务需求调整。
Docker容器部署acme.sh(核心操作)
执行以下命令,创建部署目录并编写Docker Compose配置文件,核心代码保持不变:
bash
mkdir -p /etc/nginx/ssl
mkdir acme.sh && cd acme.sh
cat > docker-compose.yaml <<-EOF
services:
acme-sh:
image: neilpang/acme.sh
container_name: acme.sh
environment:
Tencent_SecretId: "替换为腾讯云 SecretId"
Tencent_SecretKey: "替换为腾讯云 SecretKey"
volumes:
- ./out:/acme.sh
- /etc/nginx/ssl/:/etc/nginx/ssl/
network_mode: host
command: daemon
stdin_open: true
tty: true
restart: no
EOF
证书申请与部署全流程(含自动续签配置)
以下操作均在acme.sh部署目录(\~/acme\.sh)下执行,核心命令保持不变,补充术语说明及注意事项:
步骤1:启动acme.sh容器
bash
root@VM-0-9-ubuntu:~/acme.sh# ls
docker-compose.yaml
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# docker compose up -d
[+] up 1/1
✔ Container acme.sh Started 0.2s
说明:容器启动后将以守护进程(daemon)模式运行,为后续证书自动续签提供基础;restart: no表示容器不会自动重启,若需保障高可用,可修改为restart: always。
步骤2:注册ACME账号(绑定邮箱)
bash
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# # 1. 邮箱注册(用于接收证书过期提醒及账号验证)
root@VM-0-9-ubuntu:~/acme.sh# docker exec acme.sh acme.sh --register-account -m my@example.com
[Thu Apr 9 12:34:14 UTC 2026] Account key creation OK.
[Thu Apr 9 12:34:14 UTC 2026] No EAB credentials found for ZeroSSL, let's obtain them
[Thu Apr 9 12:34:16 UTC 2026] Registering account: https://acme.zerossl.com/v2/DV90
[Thu Apr 9 12:34:20 UTC 2026] Registered
[Thu Apr 9 12:34:20 UTC 2026] ACCOUNT_THUMBPRINT='n2jEKHv6l-AfB5plPhPwyqsgDXnUjVceHeHJbIsGmsk'
说明:需将my@example\.com替换为实际邮箱地址,该邮箱将用于接收证书相关通知(如续签提醒、异常通知);本次注册默认使用ZeroSSL作为CA机构(证书颁发机构),acme.sh会自动获取EAB凭证完成注册。

步骤3:申请泛域名证书(基于DNS验证)
bash
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# # 2. 申请域名证书
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# docker exec acme.sh acme.sh --issue --dns dns_tencent -d example.com -d *.example.com
[Thu Apr 9 12:25:50 UTC 2026] Using CA: https://acme.zerossl.com/v2/DV90
[Thu Apr 9 12:25:50 UTC 2026] Multi domain='DNS:example.com,DNS:*.example.com'
[Thu Apr 9 12:25:56 UTC 2026] Getting webroot for domain='example.com'
[Thu Apr 9 12:25:56 UTC 2026] Getting webroot for domain='*.example.com'
[Thu Apr 9 12:25:56 UTC 2026] Adding TXT value: P9FwylmqWM5A3N6VuVYCaAuS87UlHVGss358HVp1Ioc for domain: _acme-challenge.example.com
[Thu Apr 9 12:25:58 UTC 2026] The TXT record has been successfully added.
[Thu Apr 9 12:25:58 UTC 2026] Let's check each DNS record now. Sleeping for 20 seconds first.
[Thu Apr 9 12:26:18 UTC 2026] You can use '--dnssleep' to disable public dns checks.
[Thu Apr 9 12:26:18 UTC 2026] See: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
[Thu Apr 9 12:26:18 UTC 2026] Checking example.com for _acme-challenge.example.com
[Thu Apr 9 12:26:28 UTC 2026] Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 28
[Thu Apr 9 12:26:38 UTC 2026] Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 28
[Thu Apr 9 12:26:38 UTC 2026] Success for domain example.com '_acme-challenge.example.com'.
[Thu Apr 9 12:26:38 UTC 2026] All checks succeeded
[Thu Apr 9 12:26:38 UTC 2026] example.com is already verified, skipping dns-01.
[Thu Apr 9 12:26:38 UTC 2026] Verifying: *.example.com
[Thu Apr 9 12:26:40 UTC 2026] Processing. The CA is processing your order, please wait. (1/30)
[Thu Apr 9 12:26:46 UTC 2026] Success
[Thu Apr 9 12:26:46 UTC 2026] Removing DNS records.
[Thu Apr 9 12:26:46 UTC 2026] Removing txt: P9FwylmqWM5A3N6VuVYCaAuS87UlHVGss358HVp1Ioc for domain: _acme-challenge.example.com
[Thu Apr 9 12:26:49 UTC 2026] Successfully removed
[Thu Apr 9 12:26:49 UTC 2026] Verification finished, beginning signing.
[Thu Apr 9 12:26:49 UTC 2026] Let's finalize the order.
[Thu Apr 9 12:26:49 UTC 2026] Le_OrderFinalize='https://acme.zerossl.com/v2/DV90/order/6adcbsqM4DFmuwLylp3Q2A/finalize'
[Thu Apr 9 12:26:50 UTC 2026] Order status is 'processing', let's sleep and retry.
[Thu Apr 9 12:26:50 UTC 2026] Sleeping for 15 seconds then retrying
[Thu Apr 9 12:27:05 UTC 2026] Polling order status: https://acme.zerossl.com/v2/DV90/order/6adcbsqM4DFmuwLylp3Q2A
[Thu Apr 9 12:27:08 UTC 2026] Downloading cert.
[Thu Apr 9 12:27:08 UTC 2026] Le_LinkCert='https://acme.zerossl.com/v2/DV90/cert/7C3WW9Y8L4jbzkTn_eKpcw'
[Thu Apr 9 12:27:12 UTC 2026] Cert success.
-----BEGIN CERTIFICATE-----
MIIDjDCCAzKgAwIBAgIRAK1aj5ZYof7ny8lpTIhXnl8wCgYIKoZIzj0EAwIwRjEL
MAkGA1UEBhMCQVQxFTATBgNVBAoTDFplcm9TU0wgR21iSDEgMB4GA1UEAxMXWmVy
b1NTTCBFQ0MgRFYgU1NMIENBIDIwHhcNMjYwNDA5MDAwMDAwWhcNMjYwNzA4MjM1
OTU5WjAXMRUwEwYDVQQDEwxrdWJlb3Blci5jb20wWTATBgcqhkjOPQIBBggqhkjO
PQMBBwNCAAQLLG/T/9YfjztSV696y19UnriILzz2RJVl9F3j6tFsZkMbuHYNTR51
ZV3oQCxdFKjB3dUI7hutU1DJqE9sErszo4ICLjCCAiowHwYDVR0jBBgwFoAUlEWf
2lFHcdVzrqwdqwhyEm2tfGIwHQYDVR0OBBYEFDFD/3fWHT4SFR9yvq1HM3A3Mc+I
MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMBMGA1UdIAQMMAowCAYGZ4EMAQIBMG4GCCsGAQUFBwEBBGIwYDA5BggrBgEF
BQcwAoYtaHR0cDovL2NydC5zZWN0aWdvLmNvbS9aZXJvU1NMRUNDRFZTU0xDQTIu
Y3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTCCAQUGCisG
AQQB1nkCBAIEgfYEgfMA8QB2ANdtfRDRp/V3wsfpX9cAv/mCyTNaZeHQswFzF8DI
xWl3AAABnXI1rN8AAAQDAEcwRQIhAP/+ZlRILkj1hMly6ld4WyZxqIwn7zQGcDzf
JVbz+6/SAiAmrvQExf3gUvCy48ZadiO+lKMULlAM73HcnqamCTY9pwB3AMijxH/H
s625NWsBP2p6Em3jOk5DpcZG+ZetOXWZHc+aAAABnXI1rSYAAAQDAEgwRgIhAPZd
Dk72rqI6Qb2a6OikDci6I+IEZ3112wl7zDBY7/ULAiEAoRlKRmLjjnQlkv7TRNJX
bfc7tid9AXNsIT7eXF+stxgwJwYDVR0RBCAwHoIMa3ViZW9wZXIuY29tgg4qLmt1
YmVvcGVyLmNvbTAKBggqhkjOPQQDAgNIADBFAiEA1SxHPTj/xMNBcWrc9UNRL8oY
HF7cu+mxugOnP5eVxjUCIHhMebR/Ih7sMOV/pNhxLLoy6V8tpT86lcfQc0oDqRg5
-----END CERTIFICATE-----
[Thu Apr 9 12:27:12 UTC 2026] Your cert is in: /acme.sh/example.com_ecc/example.com.cer
[Thu Apr 9 12:27:12 UTC 2026] Your cert key is in: /acme.sh/example.com_ecc/example.com.key
[Thu Apr 9 12:27:12 UTC 2026] The intermediate CA cert is in: /acme.sh/example.com_ecc/ca.cer
[Thu Apr 9 12:27:12 UTC 2026] And the full-chain cert is in: /acme.sh/example.com_ecc/fullchain.cer
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh#
关键说明 :出现上述内容(含「Cert success.」、完整证书内容及证书文件路径提示),表示泛域名证书申请成功,可继续后续证书部署操作;若未出现此类内容(如提示「link dead」「link fetch error」等报错),说明证书申请失败,需重新执行本次证书申请命令(docker exec acme.sh acme.sh --issue --dns dns_tencent -d example.com -d *.example.com)。重新申请前需排查:1. 网络连通性(确保服务器能正常访问acme.zerossl.com,开放443端口);2. SecretId/SecretKey权限(子账号需配置DNSPod相关操作权限);3. 可添加\-\-dnssleep 300参数跳过公共DNS校验,避免curl错误码28导致的验证异常。
-
命令中
\-\-dns dns\_tencent指定使用腾讯云DNSPod解析方式完成ACME验证,acme.sh会自动调用腾讯云API添加/删除TXT验证记录,无需手动操作DNS解析。 -
\-d example\.com \-d \*\.example\.com表示同时申请主域名(example.com)和泛域名(所有子域名)的证书,需将example.com替换为实际域名。 -
执行过程中出现的curl错误码28(操作超时),通常不影响验证结果,acme.sh会自动重试;若频繁出现,可添加
\-\-dnssleep 300参数(等待300秒后跳过公共DNS校验)。 -
证书默认保存路径为容器内
/acme\.sh/example\.com\_ecc/,包含证书文件、私钥文件、中间CA证书及完整链证书,acme.sh会自动配置证书自动续签任务(默认每60天续签一次)。

步骤4:部署证书到应用服务器(以nginx为例)
bash
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# # 3. 安装证书到指定的目录 (也可复制到目标位置)
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# docker exec acme.sh acme.sh --install-cert -d example.com --key-file /etc/nginx/ssl/server.key --fullchain-file /etc/nginx/ssl/server.crt
[Thu Apr 9 12:30:18 UTC 2026] The domain 'example.com' seems to already have an ECC cert, let's use it.
[Thu Apr 9 12:30:18 UTC 2026] Installing key to: /etc/nginx/ssl/server.key
[Thu Apr 9 12:30:18 UTC 2026] Installing full chain to: /etc/nginx/ssl/server.crt
说明:
-
通过
\-\-install\-cert命令将证书部署到指定路径(/etc/nginx/ssl/),该路径已通过Docker挂载到宿主机,便于nginx服务直接读取。 -
证书部署完成后,需重启或重载nginx服务,使证书生效,可执行命令:
service nginx force\-reload(根据实际nginx启动方式调整)。 -
验证证书部署结果:执行
ls \-l /etc/nginx/ssl/查看证书文件是否存在,确认文件权限正确(私钥文件server.key建议权限为600,证书文件server.crt建议权限为644)。
bash
root@VM-0-9-ubuntu:~/acme.sh# ls -l /etc/nginx/ssl/server.key
-rw------- 1 root root 227 Apr 9 20:30 /etc/nginx/ssl/server.key
root@VM-0-9-ubuntu:~/acme.sh#
root@VM-0-9-ubuntu:~/acme.sh# ls -l /etc/nginx/ssl/server.crt
-rw-r--r-- 1 root root 3657 Apr 9 20:30 /etc/nginx/ssl/server.crt

自动续签说明(核心特性)
-
自动续签机制:acme.sh容器启动后,会自动创建定时任务(crontab),默认每60天检查一次证书有效期,当证书剩余有效期不足30天时,自动完成续签并更新证书文件,无需人工干预。
-
续签后生效:证书续签完成后,若需应用服务(如nginx)立即加载新证书,可在安装证书时添加
\-\-reloadcmd \&\#34;service nginx force\-reload\&\#34;参数,实现续签后自动重载服务,示例命令:
bash
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/server.key \
--fullchain-file /etc/nginx/ssl/server.crt \
--reloadcmd "service nginx force-reload"
- 续签状态查看:可通过命令
docker exec acme\.sh acme\.sh \-\-list查看已申请的证书信息及续签状态,确认自动续签任务是否正常。
常见问题与注意事项
-
SecretId/SecretKey权限:若使用子账号API密钥,需确保子账号已配置DNSPod相关操作权限(具体策略参考腾讯云官方文档),否则会导致DNS解析验证失败。
-
网络权限:服务器需开放 outbound 443端口,确保能正常访问ACME服务器(ZeroSSL、Let's Encrypt等),否则会出现证书申请超时。
-
证书路径权限:挂载的证书目录(如
/etc/nginx/ssl/)需确保宿主机和容器都有读写权限,避免证书部署失败。 -
报错处理:若出现"link dead"报错(访问acme.zerossl.com相关链接失败),需检查网络连通性,或更换CA机构(如切换为Let's Encrypt)。