Deploy Certbot Using Docker Compose

服务器上,使用Docker Compose部署和管理各种服务,体验相当好。部署Certbot,申请和更新免费SSL证书,有些不同,记录一下相关操作。

首先,很多DNS服务商已经在提供DNS服务的同时,提供了免费SSL服务。如果这种服务能解决SSL免费证书的需求,就没必要部署Certbot了。例如Cloudflare、DNSPod等。

使用Docker Compose部署Certbot的特点:

  • Docker Compose部署和管理容器,比较清晰和方便。
    • 比如直接运行容器(即使用docker run命令运行容器),能记录容器的配置,方便查看和维护。
  • Certbot容器无需一直保持运行,只需启动一下,申请或续签SSL免费证书。
    • 只要得到SSL免费证书的文件,即可停止运行。
    • 需要设置定时运行,执行续签证书。
  • 需要使用SSL免费证书的服务(例如Nginx),需要把证书文件mount到对应的容器。

1. Docker Compose部署Certbot

创建好部署目录,以下例子采用/opt/docker/certbot

先创建Cloudflare的认证配置文件:/opt/docker/certbot/etc/letsencrypt/certbot-dns-cloudflare-credentials.ini。该文件格式如下:

dns_cloudflare_api_token=<your-cloudflare-api-token>

注意,/opt/docker/certbot/etc/letsencrypt最好设置拥有者为root用户,并保证只有root可读写,提高安全性。

sudo chown -R root:root /opt/docker/certbot/etc/letsencrypt

再创建docker-compose.yaml文件,该文件内容如下:

# https://hub.docker.com/r/certbot/dns-cloudflare
services:
  certbot:
    image: certbot/dns-cloudflare:latest
    volumes:
      - ./etc/letsencrypt:/etc/letsencrypt
      - ./log:/var/log/letsencrypt
    command: certonly --agree-tos --non-interactive -m xxx@abc.com --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/certbot-dns-cloudflare-credentials.ini -d example.com,*.example.com

networks:
  default:
    name: default-net
    external: true

注意:

  • 由于采用Cloudflare的DNS服务,所以采用dns-cloudflare的Docker镜像。
  • --agree-tos,同意ACME订阅协议(the ACME server’s Subscriber Agreement)
  • --non-interactive,非交互式运行,即运行过程中不需要询问用户输入。
    • 当客户端发现参数缺失时会给出相应的说明。
  • -m,即--email,设置域名所有者的EMail。
  • -d,设置SSL证书相关域名。
    • 多个域名可以设置多个-d实现。
    • 也可以1个-d设置多个域名,但域名之间需要英文逗号(,)分隔,并且主域名放第一位,子域名随后。
    • 支持泛域名,即*.+主域名,避免设置多个子域名。
  • 最后的networks可以不设。
    • 这里设置了默认加入网络default-net,方便通过网络访问其它容器。

最后启动。由于无需一直保持运行,所以不用添加-d参数。如果无错误输出,则成功运行。

docker compose up

2. 使用SSL证书

对于HTTP服务的容器,只需把SSL证书文件mount到相关容器即可。

比如Nginx,其docker-compose.yamlvolumes配置如下:

volumes:
  - ../certbot/etc/letsencrypt/archive:/etc/letsencrypt/archive:ro
  - ../certbot/etc/letsencrypt/live:/etc/letsencrypt/live:ro

对应网站的server配置SSL证书:

server {
  server_name example.com;
  listen 443 ssl;
  ...
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ...

3. 自动续签

这里使用Systemd Timer实现定时自动renew证书。

创建服务管理单元,文件/opt/docker/certbot/deploy_conf/certbot-renew.service

[Unit]
Description=Certbot renew
Requires=network-online.target

[Service]
Type=oneshot
ExecStart=docker compose -f /opt/docker/certbot/docker-compose.yaml start 

[Install]
WantedBy=multi-user.target

创建定时器单元,文件/opt/docker/certbot/deploy_conf/certbot-renew.timer

[Unit]
Description=Auto run certbot renew
Requires=certbot-renew.service

[Timer]
# 周一和周四的凌晨3点执行
OnCalendar=Mon,Thu *-*-* 03:00:00
# 在5分钟以内,随机延迟执行
RandomizedDelaySec=5min
Unit=certbot-renew.service

[Install]
WantedBy=multi-user.target

部署:

sudo ln -s /opt/docker/certbot/deploy_conf/certbot-renew.service /etc/systemd/system/certbot-renew.service
sudo ln -s /opt/docker/certbot/deploy_conf/certbot-renew.timer /etc/systemd/system/certbot-renew.timer
sudo systemctl daemon-reload 
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timer

注意:这里没实现自动续签成功后(即SSL证书文件更新后),自动更新Nginx。

使用 Hugo 构建
主题 StackJimmy 设计