docker使用certbot自动申请和续期SSL证书
编辑
9
2025-09-24
1.先拉取certbot镜像
docker pull certbot/certbot:v3.1.0
2.nginx的的配置
需要先配置好 nginx
的配置,并且生效
注:nginx容器的 /usr/share/nginx/html
需要和宿主机的 /app/nginx/html
映射
server {
listen 80;
server_name a.domain.com;
location ^~ /.well-known/acme-challenge/ {
allow all;
root /usr/share/nginx/html;
}
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl;
server_name a.domain.com;
ssl_certificate /etc/nginx/cert/a.domain.com.pem;
ssl_certificate_key /etc/nginx/cert/a.domain.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://app; # 需要修改为自己的应用
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
3.创建自动申请和续期的bash脚本
变量 DOMAINS
是待申请和续期的域名,是一个数组,自行修改
LINUX目录结构,修改时需要完整替换
/app/nginx/cert nginx上使用的ssl证书目录
/app/nginx/certbot/ssl certbot上的ssl缓存
/app/nginx/certbot/logs certbot日志
/app/nginx/html nginx默认的html路径
DOMAINS=("a.domain.com" "b.domain.com")
NUMBER=0
ISAPPLY=0
CREATION_TIME=$(date +%s)
CURRENT_TIME=$(date +%s)
DIFF_DAYS=0
for DOMAIN in "${DOMAINS[@]}"; do
echo ${DOMAIN}
if [ -e "/app/nginx/cert/${DOMAIN}.pem" ]; then
# 检查当前证书是否过期
let CREATION_TIME=$(stat -c %Y "/app/nginx/cert/${DOMAIN}.pem")
if [ "$CREATION_TIME" -eq 0 ]; then
echo "该系统不支持获取文件的修改时间"
continue
fi
let CURRENT_TIME=$(date +%s)
let DIFF_DAYS=$(( (CURRENT_TIME - CREATION_TIME) / 86400 ))
else
echo "当前证书不存在,准备申请证书..."
let DIFF_DAYS=100
fi
# 证书创建时间与当前时间相差80天,执行创建
if [ "$DIFF_DAYS" -ge 80 ]; then
let ISAPPLY=1
# 清空上次证书
rm -rf /app/nginx/certbot/ssl/${DOMAIN}
# 生成证书
if [ -n "$(docker ps -q -f name=certbot)" ]; then
docker rm -f certbot
echo "容器 certbot 已被移除。"
fi
docker run -d \
--name certbot \
-v /app/nginx/certbot/ssl:/etc/letsencrypt/archive \
-v /app/nginx/certbot/logs:/var/log/letsencrypt \
-v /app/nginx/html:/data/letsencrypt \
certbot/certbot:v3.1.0 certonly --webroot --email abc@qq.com --agree-tos --no-eff-email --webroot-path=/data/letsencrypt -d ${DOMAIN}
NUMBER=0
# 等待,并循环检查
while true; do
if [ -e "/app/nginx/certbot/ssl/${DOMAIN}" ]; then
if [ -f "/app/nginx/certbot/ssl/${DOMAIN}/fullchain1.pem" ]; then
echo "${DOMAIN}的私钥文件[fullchain.pem]存在,正在重命名并移动..."
mv -f /app/nginx/certbot/ssl/${DOMAIN}/fullchain1.pem /app/nginx/cert/${DOMAIN}.pem
echo "${DOMAIN}的私钥文件移动成功"
else
echo "${DOMAIN}的私钥文件[fullchain.pem]不存在"
fi
if [ -f "/app/nginx/certbot/ssl/${DOMAIN}/privkey1.pem" ]; then
echo "${DOMAIN}的公钥文件[privkey1.pem]存在,正在重命名并移动..."
mv -f /app/nginx/certbot/ssl/${DOMAIN}/privkey1.pem /app/nginx/cert/${DOMAIN}.key
echo "${DOMAIN}的公钥文件移动成功"
else
echo "${DOMAIN}的公钥文件[privkey1.pem]不存在"
fi
docker rm -f certbot
echo "${DOMAIN}证书申请成功"
break
else
echo "等待证书申请中...$NUMBER"
fi
sleep 5
let NUMBER=NUMBER+1
# 如果等待时间超过60s,则继续休眠10分钟(Let's Encrypt限制请求)
if [ "$NUMBER" -ge 12 ]; then
echo "限制请求,等待10分钟后继续执行..."
sleep 600
docker restart certbot
let NUMBER=0
fi
done
else
echo "未满足到期前10天,终止证书申请"
fi
done
if [ $ISAPPLY -eq 1 ]; then
docker restart nginx
fi
脚本原理:通过检测 nginx
的 cert证书
是否已使用80天(按照3个月的证书有效期,即为到期前10天),当满足条件时,自动创建 certbot
容器,certbot
会按照当前域名去申请证书。当 certbot
执行时,会在 /app/nginx/html
里生成验证文件,并且由于 nginx
的事前配置,会顺利通过所有权的验证,进而生成证书。
certbot
的容器会生成四个证书,我们只需要 fullchain1.pem
和 privkey1.pem
,将两个证书文件重命名,并移动到 nginx
所需要的证书目录下,即完成证书的申请和续期。
4.自动续期
使用 crontab
定时执行脚本,达到自动续期的效果
crontab -e
输入定时任务,示例为每日凌晨1点执行脚本,假定脚本位置是:/app/nginx/certbot/install.sh
0 1 * * * /app/nginx/certbot/install.sh
如果当前linux未使用bash执行,需要指定为bash执行
0 1 * * * /bin/bash /app/nginx/certbot/install.sh
- 1
- 0
-
分享