Docker与Kubernetes环境下的SSL自动化方案

a
admin
作者
2026-07-17
发布日期
约 17 分钟
阅读时间

Docker和Kubernetes环境下,SSL证书管理是另一个维度的问题。容器是临时的、可漂移的,传统的”申请证书 → 部署到服务器”模式不适用。

本文整理容器环境下的SSL自动化方案,从单机Docker到Kubernetes集群。

容器环境SSL的挑战

挑战一:容器无状态

容器重启后数据丢失,证书不能存在容器内部。

解决:用Volume挂载、或用Secret存储证书。

挑战二:自动扩缩容

Pod可能在任何节点启动,证书需要跟着Pod走。

解决:用Kubernetes Secret、或用Ingress统一终止SSL。

挑战三:多容器共享

一个域名可能被多个容器服务,证书需要共享。

解决:用共享Volume、或用反向代理统一SSL。

挑战四:自动续签

容器内跑cron不优雅,续签后要重启多个容器。

解决:用专门的证书管理器(cert-manager)。

方案一:Docker Compose + acme.sh

适合单机多容器场景。

架构

acme.sh容器 → 申请证书 → 挂载Volume → Nginx容器读取

docker-compose.yml

version: '3'

services:
  certbot:
    image: neilpang/acme.sh
    container_name: acme
    volumes:
      - ./ssl:/acme.sh
      - /var/run/docker.sock:/var/run/docker.sock
    command: >
      --issue --dns dns_ali
      -d example.com -d *.example.com
    environment:
      - Ali_Key=${ALI_KEY}
      - Ali_Secret=${ALI_SECRET}
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl/example.com:/etc/nginx/ssl:ro
    depends_on:
      - certbot
    restart: unless-stopped

续签后自动重载Nginx

acme.sh的 --reloadcmd 可以调用Docker API重载容器:

acme.sh --install-cert -d example.com \
    --key-file /acme.sh/example.com.key \
    --fullchain-file /acme.sh/example.com.crt \
    --reloadcmd "curl -X POST --unix-socket /var/run/docker.sock http://localhost/containers/nginx/restart"

方案二:Traefik自动SSL

Traefik是云原生反向代理,内置Let’s Encrypt自动证书。

docker-compose.yml

version: '3'

services:
  traefik:
    image: traefik:v3.0
    command:
      - --providers.docker=true
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.le.acme.email=your@email.com
      - --certificatesresolvers.le.acme.storage=/acme.json
      - --certificatesresolvers.le.acme.dnschallenge=true
      - --certificatesresolvers.le.acme.dnschallenge.provider=alidns
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/acme.json
    environment:
      - ALICLOUD_ACCESS_KEY=${ALI_KEY}
      - ALICLOUD_SECRET_KEY=${ALI_SECRET}
    restart: unless-stopped

  whoami:
    image: traefik/whoami
    labels:
      - traefik.http.routers.whoami.rule=Host(`example.com`)
      - traefik.http.routers.whoami.tls=true
      - traefik.http.routers.whoami.tls.certresolver=le

优势

  • 全自动,加个label就HTTPS
  • 支持通配符
  • 支持Let’s Encrypt和ZeroSSL

劣势

  • 绑定Traefik生态
  • 配置语法有学习曲线

方案三:Caddy自动HTTPS

Caddy是现代Web服务器,最大特色是默认自动HTTPS

Caddyfile

example.com {
    reverse_proxy localhost:8080
}

*.example.com {
    reverse_proxy localhost:8081
}

docker-compose.yml

version: '3'

services:
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    restart: unless-stopped

volumes:
  caddy_data:
  caddy_config:

启动后Caddy自动申请证书、自动续签、自动重定向HTTP到HTTPS。

优势

  • 配置极简
  • 全自动HTTPS
  • 支持通配符

劣势

  • 生态不如Nginx
  • 插件较少

方案四:Kubernetes + cert-manager

cert-manager是Kubernetes上的证书管理标准。

架构

cert-manager → 申请证书 → 存储到Secret → Ingress/Pod挂载

安装cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml

配置ClusterIssuer(Let’s Encrypt):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    email: your@email.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-key
    solvers:
      - http01:
          ingress:
            class: nginx

配置DNS验证的ClusterIssuer(阿里云):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-dns
spec:
  acme:
    email: your@email.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-dns-key
    solvers:
      - dns01:
          webhook:
            groupName: cert-manager-webhook-aliyun
            solverName: alidns-solver
            config:
              accessKeyId: ${ALI_KEY}
              accessKeySecret: ${ALI_SECRET}
              regionId: cn-hangzhou

申请证书

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com
  namespace: default
spec:
  secretName: example-com-tls
  issuerRef:
    name: letsencrypt
    kind: ClusterIssuer
  dnsNames:
    - example.com
    - www.example.com

Ingress使用证书

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
    - hosts:
        - example.com
      secretName: example-com-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80

cert-manager会自动申请证书、自动续签、自动更新Secret。

方案五:Nginx Ingress Controller

Kubernetes上最常用的方案,Ingress Controller内置cert-manager集成。

安装Nginx Ingress

helm install ingress-nginx ingress-nginx/ingress-nginx

配置Ingress自动HTTPS

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - example.com
      secretName: example-com-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80

优势

  • 标准Kubernetes方案
  • 集中SSL终止
  • 自动续签
  • 支持通配符

选型建议

| 场景 | 推荐方案 |

|——|———-|

| 单机Docker Compose | acme.sh + Volume挂载 |

| 单机多容器,要极简 | Caddy |

| 单机多容器,要灵活 | Traefik |

| 小规模K8s集群 | Nginx Ingress + cert-manager |

| 大规模K8s集群 | cert-manager + 多Issuer |

| 不想学新工具 | acme.sh + 手动挂载 |

容器SSL的最佳实践

1. 证书和代码分离

证书用Volume/Secret挂载,不要打包进镜像。

2. 集中SSL终止

用Ingress/反向代理统一处理SSL,后端服务用HTTP,简化架构。

3. 自动续签 + 自动重载

续签后要触发Web服务器重载。Docker用API触发restart,K8s用reloader控制器。

4. 备份证书存储

acme.json、Secret等证书存储要定期备份。

5. 监控证书状态

用Prometheus + blackbox_exporter监控所有Ingress的证书。

结语

容器环境下的SSL自动化比传统服务器复杂,但用对工具可以更省心。小规模用Caddy/Traefik一键搞定,大规模用cert-manager集中管理。核心思路是让证书管理成为基础设施的一部分,而不是每个应用自己的事

本文到此结束