Docker+certbot+Nginx实现自动续期https证书

使用 Docker 和 Certbot 配置 HTTPS 的完整指南,并自动续期 https 证书。

下载 Certbot 镜像

1
docker pull certbot/certbot

创建 docker-compose.yml 文件

1
2
3
4
5
6
7
mkdir certbot
cd certbot/
mkdir certs

# 创建 `docker-compose.yml` 文件
cd /root
vim docker-compose.yml

docker-compose.yml 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# version '3'

networks:
my_network:
driver: bridge

services:
days_matter:
image: days_matter:1.0.0
container_name: days_matter
networks:
- my_network
ports:
- '21021:21021'
volumes:
- /root/days_matter:/app
restart: always
environment:
TZ: Asia/Shanghai
ASPNETCORE_ENVIRONMENT: Production

jytang:
image: jytang:1.0.0
container_name: jytang
networks:
- my_network
ports:
- '21022:21021'
volumes:
- /root/jytang:/app
restart: always
environment:
TZ: Asia/Shanghai
ASPNETCORE_ENVIRONMENT: Production

nginx:
image: nginx:latest
container_name: nginx
networks:
- my_network
ports:
- '80:80'
- '443:443'
volumes:
- /root/nginx/conf/conf.d:/etc/nginx/conf.d # 动态配置目录
- /root/nginx/conf/nginx.conf:/etc/nginx/nginx.conf # 主配置文件
- /root/nginx/html:/usr/share/nginx/html # 网站根目录
- /root/certbot/certs:/etc/letsencrypt # 证书持久化存储(关键!)
restart: always
environment:
TZ: Asia/Shanghai
command: >
sh -c "nginx -g 'daemon off;'"
depends_on:
- days_matter
- yyan
- jytang
- certbot # 确保 Certbot 先启动(仅首次申请时必要)

certbot:
image: certbot/certbot
container_name: certbot
networks:
- my_network
volumes:
- /root/certbot/certs:/etc/letsencrypt # 证书存储(与 Nginx 共享)
restart: always

创建 nginx.conf 文件

1
vim /root/nginx/conf/conf.d/default.conf

域名验证,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
server_name xxx.com; # 替换为你的域名
#配置http验证可访问
location ^~ /.well-known/acme-challenge/ {
#此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,
#而宿主机的又与certbot容器中命令--webroot-path指定目录一致,
#从而就整个串起来了,解决了http验证问题
root /etc/letsencrypt;
}
# 其他请求重定向到HTTPS
location / {
rewrite ^(.*)$ https://$host$1 permanent;
}
}

启动 docker-compose服务

1
docker compose up -d

测试证书发放

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

1
docker-compose run --rm certbot certonly --webroot --webroot-path /etc/letsencrypt --dry-run -d xxx.com

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

正式获取证书

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

1
docker-compose run --rm certbot certonly --webroot --webroot-path /etc/letsencrypt -d xxx.com

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

生成结果文件

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

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

创建 HTTPS 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 443 ssl;
server_name xxx.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;
}

重启 Nginx

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

1
docker-compose restart nginx

配置定时任务自动续期

选择 vim 编辑器:

1
2
select-editor
# 使用 vim.tiny

表达式所在的目录:

  • /etc/crontab 系统定时任务,一般不推荐修改
  • /var/spool/cron/crontabs/ 目录下,各个用户名下面的定时任务
1
2
3
4
5
crontab -e ## 编辑任务
crontab -l ## 查看任务
crontab -u username -l ## 列出指定用户的Crontab文件
crontab -r ## 删除当前用户的Crontab文件
crontab -u username -e ## 编辑指定用户的Crontab文件。

Crontab 的时间格式由五个字段组成,分别表示分钟、小时、日期、月份和星期几。

使用 cron 表达式,工具 https://tool.lu/crontab/

为了避免证书过期,设置一个定时任务每隔 3 个月,15 号自动续期证书并重启 Nginx:

1
0 0 15 */3 * root cd /root && docker-compose run --rm certbot renew --force-renewal && docker-compose restart nginx

--force-renewal 强制续签

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

使用 linux 自带的 cron.service 定时任务,执行命令

1
2
3
systemctl status cron.service
systemctl stop cron.service
systemctl start cron.service

参考地址

https://letsencrypt.org/
https://certbot.eff.org/