Docker Compose 部署certbot实现TLS证书签发和续期

前提条件

  • 有现成的域名、公网IP
  • 可访问公网的服务器
  • 可用的邮箱

开始部署

1. Certbot 镜像拉取

shell 复制代码
docker pull certbot/certbot:v5.1.0

2. 创建 docker-compose.yml 文件

yml 复制代码
services:
  nginx:
    image: nginx:1.25.4
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/localtime:/etc/localtime:ro                  # 和服务器时间同步
      - /root/docker/nginx/nginx/:/etc/nginx/             # 主配置目录
      - /root/docker/nginx/nginx/certs/:/etc/letsencrypt  # 证书配置目录
      - /root/docker/nginx/html/:/usr/share/nginx/html    # 网站根目录
      - /root/docker/nginx/log/:/var/log/nginx            # 日志目录
    networks:
      - nginx-network
    restart: always
    entrypoint: ["/docker-entrypoint.sh"]
    command: ["nginx", "-g", "daemon off;"]
    stop_signal: SIGQUIT
    logging:
      driver: json-file
    networks: 
      - nginx-network
    depends_on:
      - certbot   # 确保 Certbot 先启动(非必须)

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - /root/docker/nginx/nginx/certs/:/etc/letsencrypt      # 证书存储目录(与 Nginx 共享)
      - /root/docker/nginx/html/:/var/www/html                # HTTP 验证所需的 Webroot
    networks: 
      - nginx-network
    restart: always

networks:
  nginx-network:
    external: true
    driver: bridge

3. 修改 nginx.conf 或 创建 tansuo.conf 文件

yml 复制代码
server {
    listen 80;
    server_name tansuo.com;  # 替换为你的域名
    #配置http验证可访问
    location ^~ /.well-known/acme-challenge/ {
        #此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令--webroot-path指定目录一致,从而就整个串起来了,解决了http验证问题
        root /etc/letsencrypt;
    }
    # 其他请求重定向到HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

4. 启动服务

js 复制代码
docker compose -f docker-compose.yml up -d

5. 测试证书发放

运行以下命令测试证书发放是否正常:

js 复制代码
docker compose run --rm certbot certonly --webroot --webroot-path /etc/letsencrypt --dry-run -d tansuo.com

如果输出 The dry run was successful.,说明测试成功。

如果出现::404字样,首先检查yml配置是否和文章中的匹配,其次检查域名和公网IP是否正确绑定。最后重启nginx服务。

6. 正式获取证书

如果测试成功,去掉 --dry-run 参数正式获取证书:

js 复制代码
docker compose run --rm certbot certonly --webroot --webroot-path /etc/letsencrypt -d tansuo.com

按照提示输入邮箱等信息,完成证书申请。

7. 生成证书文件

Certbot 会在 /root/docker/nginx/nginx/certs/live/tansuo.com/ 目录下生成证书文件,包括:

  • fullchain.pem:完整的证书链
  • privkey.pem:私钥

8. 创建 HTTPS 配置文件

在你自定义的配置文件,比如上文创建的tansuo.conf 中配置 HTTPS信息:

js 复制代码
server {
    listen       443 ssl;
    server_name  tansuo.com;

    ssl_certificate /etc/letsencrypt/live/xxx.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/xxx.com/privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location /api/ {
        proxy_pass http://gateway:18080/;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

将此文件挂载到 Nginx 的配置目录中,我的tansuo.conf位于conf.d目录下。

9. 重启 Nginx

重新加载 Nginx 配置以应用 HTTPS:

js 复制代码
docker compose restart nginx

10. 配置定时任务自动续期

为了避免证书过期,创建一个检查脚本,设置定时任务为每月 1 号凌晨 2 点检查证书是否过期&自动续期证书&重启 Nginx: vi renew-certbot.sh

bash 复制代码
#!/bin/bash

# Certbot SSL 证书自动续期脚本(针对90天有效期优化)
# 证书有效期:90天,推荐每30天检查续期

echo "=== SSL 证书自动续期脚本开始执行 ==="
echo "执行时间: $(date)"
echo "证书类型: Let's Encrypt (90天有效期)"

# 设置变量
LOG_FILE="/var/log/certbot-renew.log"
COMPOSE_DIR="/root/docker"

# 记录开始时间
START_TIME=$(date +%s)

# 检查必要目录
if [ ! -d "$COMPOSE_DIR" ]; then
    echo "错误: Docker Compose 目录不存在: $COMPOSE_DIR" | tee -a "$LOG_FILE"
    exit 1
fi

# 切换到工作目录
cd "$COMPOSE_DIR" || {
    echo "错误: 无法切换到目录 $COMPOSE_DIR" | tee -a "$LOG_FILE"
    exit 1
}

echo "工作目录: $(pwd)" | tee -a "$LOG_FILE"

# 检查 Docker 服务
if ! systemctl is-active --quiet docker; then
    echo "错误: Docker 服务未运行,尝试启动..." | tee -a "$LOG_FILE"
    systemctl start docker
    sleep 10
fi

# 检查证书过期时间(可选)
echo "检查证书状态..." | tee -a "$LOG_FILE"
docker compose run --rm certbot certificates 2>&1 | grep -E "(EXPIRED|VALID|Domains)" | tee -a "$LOG_FILE"

# 执行证书续期(--quiet 模式减少输出)
echo "开始证书续期检查..." | tee -a "$LOG_FILE"
docker compose run --rm certbot renew --quiet --non-interactive 2>&1 | tee -a "$LOG_FILE"

RENEW_RESULT=${PIPESTATUS[0]}

if [ $RENEW_RESULT -eq 0 ]; then
    echo "✓ 证书续期检查完成" | tee -a "$LOG_FILE"
    
    # 检查是否有证书被更新
    if docker compose run --rm certbot certificates 2>&1 | grep -q "待续期"; then
        echo "检测到证书需要更新,重启 Nginx..." | tee -a "$LOG_FILE"
        
        # 重启 Nginx
        docker compose restart nginx 2>&1 | tee -a "$LOG_FILE"
        
        if [ ${PIPESTATUS[0]} -eq 0 ]; then
            echo "✓ Nginx 重启成功" | tee -a "$LOG_FILE"
            # 发送通知(可选)
            echo "证书续期成功 - $(date)" >> /tmp/cert-renew-success.log
        else
            echo "⚠ Nginx 重启失败,请手动检查" | tee -a "$LOG_FILE"
        fi
    else
        echo "ℹ 无需续期,证书仍在有效期内" | tee -a "$LOG_FILE"
    fi
else
    echo "✗ 证书续期失败,退出码: $RENEW_RESULT" | tee -a "$LOG_FILE"
    # 可以在这里添加报警通知
    exit $RENEW_RESULT
fi

# 计算执行时间
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

echo "脚本执行完成,耗时: ${DURATION}秒" | tee -a "$LOG_FILE"
echo "完成时间: $(date)" | tee -a "$LOG_FILE"
echo "========================================" | tee -a "$LOG_FILE"

设置定时任务:

复制代码
crontab -e

添加以下内容:

bash 复制代码
# Let's Encrypt 证书自动续期(90天有效期)
# 每月1号凌晨2点检查(足够安全)
0 2 1 * * /root/renew-certbot.sh >/dev/null 2>&1

# 日志清理(每月清理一次旧日志)
0 3 1 * * find /var/log -name "certbot-renew.*.log" -mtime +30 -delete

保存后,定时任务将自动运行。


总结

通过以上步骤,使用 Certbot 为你的网站配置了TLS证书,并设置了自动续期任务。确保网站始终安全可靠,避免因证书过期导致的服务中断。

相关推荐
Mintopia3 天前
🌐 多用户并发请求下的 WebAIGC 服务稳定性技术保障
javascript·人工智能·自动化运维
温蒂来啦5 天前
Playwright最常用的功能语句汇总
自动化运维
用户7785371836966 天前
基于浏览器自动化的 Cookie 获取与复用实践
自动化运维
潘小安18 天前
🍎 Electron 桌面端应用合法性问题全流程解决指南(新手友好版)
electron·mac·自动化运维
智能运维指南23 天前
四大主流平台深度测评:2025企业自动化运维平台选型指南,自动化巡检平台适配关键场景
自动化运维·自动化运维平台·自动化运维厂商·自动化巡检·自动化运维系统·it巡检·服务器巡检
考虑考虑1 个月前
Linux查看系统基本信息
运维·后端·自动化运维
却尘1 个月前
从53个漏洞到5个:我们用Distroless把容器安全"减"出来了
后端·自动化运维·devops
老实巴交的麻匪1 个月前
(八)学习、实践、理解 CI/CD 与 DevOps:持续集成 CI,从源代码到容器镜像
运维·云原生·自动化运维
会飞的小蛮猪1 个月前
ELK运维之路(异常日志告警)
elasticsearch·自动化运维·logstash