You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose中用Certbot为多域名分别生成Let's Encrypt证书遇问题

问题描述

我拥有两个域名:

  • domain1.com
  • domain2.com

需要为每个域名分别生成包含www子域名的Let's Encrypt证书:

  • 证书1:domain1.com, www.domain1.com
  • 证书2:domain2.com, www.domain2.com

编写的docker-compose.yml配置如下:

version: '3'

services:

  webserver:
    image: domain1-com-webserver
    build:
      dockerfile: Dockerfile.webserver
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - web-root:/var/www/html
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
    networks:
      - app-network

  certbot-domain1-com:
    image: certbot/certbot
    container_name: certbot-domain1-com
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - web-root:/var/www/html
    depends_on:
      - webserver
    profiles: ["with-le"]
    command: certonly --webroot --webroot-path=/var/www/html --email info@domain1.com --agree-tos --no-eff-email --dry-run -d domain1.com -d www.domain1.com

  certbot-domain2-com:
    image: certbot/certbot
    container_name: certbot-domain2-com
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - web-root:/var/www/html
    depends_on:
      - webserver
    profiles: ["with-le"]
    command: certonly --webroot --webroot-path=/var/www/html --email info@domain2.com --agree-tos --no-eff-email --dry-run --force-renewal -d domain2.com -d www.domain2.com

volumes:
  certbot-etc:
  certbot-var:
  web-root:

networks:
  app-network:
    driver: bridge

执行命令:

$ docker-compose --profile with-le up -d

得到日志:

$ docker logs certbot-domain1-com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Simulating a certificate request for domain1.com and www.domain1.com
The dry run was successful.
$ docker logs certbot-domain2-com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Another instance of Certbot is already running.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

第一个域名的Dry-Run成功,但第二个失败,提示已有Certbot实例在运行。

解决方案

方法1:合并为单个Certbot服务顺序生成两个证书

将两个域名的证书请求合并到同一个Certbot容器,通过shell脚本顺序执行,避免并发抢占锁文件:

certbot:
  image: certbot/certbot
  container_name: certbot
  volumes:
    - certbot-etc:/etc/letsencrypt
    - certbot-var:/var/lib/letsencrypt
    - web-root:/var/www/html
  depends_on:
    - webserver
  profiles: ["with-le"]
  command: >
    sh -c "
      certonly --webroot --webroot-path=/var/www/html --email info@domain1.com --agree-tos --no-eff-email --dry-run -d domain1.com -d www.domain1.com &&
      certonly --webroot --webroot-path=/var/www/html --email info@domain2.com --agree-tos --no-eff-email --dry-run --force-renewal -d domain2.com -d www.domain2.com
    "

方法2:给第二个容器添加启动延迟

通过sleep命令让第二个Certbot容器等待第一个完成后再执行,同时依赖第一个容器保证启动顺序:

certbot-domain2-com:
  image: certbot/certbot
  container_name: certbot-domain2-com
  volumes:
    - certbot-etc:/etc/letsencrypt
    - certbot-var:/var/lib/letsencrypt
    - web-root:/var/www/html
  depends_on:
    - webserver
    - certbot-domain1-com
  profiles: ["with-le"]
  command: >
    sh -c "
      sleep 30 &&
      certonly --webroot --webroot-path=/var/www/html --email info@domain2.com --agree-tos --no-eff-email --dry-run --force-renewal -d domain2.com -d www.domain2.com
    "

方法3:分两次单独启动Certbot容器

放弃同时启动,分两次执行命令,完全避免冲突:

先执行第一个域名:

docker-compose --profile with-le up -d certbot-domain1-com

等待日志显示执行完成后,再执行第二个域名:

docker-compose --profile with-le up -d certbot-domain2-com

内容的提问来源于stack exchange,提问作者davidesp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:17:37