Acme.sh 是一款非常流行的自动 SSL 证书申请和部署工具。我在之前的博客中也多次提到用它做申请证书。然而,之前我只是直接在 VPS 中安装 acme.sh 后申请证书,然后手动拷贝证书到其他地方,仍然有些复杂。

全 Docker 化是指服务全部跑在 Docker 容器里面,对运维非常友好。但 acme.sh 似乎成了 Docker 化中的最后一环,始终没有打通。近期发现 acme.sh 已经支持在 docker-compose 中管理其他容器的证书,鉴于官方文档的简略,我替其解释一二。

首先说明,本篇博客基于 deploy to docker containers · acmesh-official/acme.sh Wiki (github.com)的第二部分,即 在 Docker 容器中的 acme.sh 为其他容器中的应用申请和部署证书

  1. 编写 docker-compose.yaml 文件如下:

    version: "3"
    services:
        nginx:
            image: nginx:alpine
            container_name: nginx
            restart: always
            ports:
                - 443:443
                - 80:80
            volumes:
                - ./nginx/conf.d:/etc/nginx/conf.d
                - ./nginx/www:/var/www
                - ./nginx/cert:/etc/nginx/ssl
            labels:
                - sh.acme.autoload.domain=example.com
            networks:
                - dockernet
    
        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:
                - 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"
            networks:
                - dockernet
    
    networks:
        dockernet:

    实际操作时需要替换 example.com 为你的域名。并且按照你的需求调整 Nginx 的相关配置。

  2. 创建文件夹用于存放证书和配置文件。按照 1. 中配置的 volumes 部分,在宿主机上新建文件夹,即:./nginx/conf.d, ./nginx/www, ./nginx/cert./acmeout
  3. 选择申请证书的方式,个人推荐 DNS 方式,例如使用 CloudFlare:

    docker exec \
     -e [email protected] \
     -e CF_Key=xxxxxxxxxx  \
     acme.sh --issue -d example.com --dns dns_cf
  4. 部署证书:

    docker exec acme.sh --deploy -d example.com  --deploy-hook docker
  5. 检查 Nginx 状态:

    docker logs -f nginx

如果 Nginx 还在反复重启,那还是检查日志对症解决。基本到这里,证书就部署完成了。