09 - Docker 部署 / Docker Deployment
Docker 部署 / Docker Deployment
容器化是 Caddy 最常见的部署方式。官方镜像体积小(~40MB),开箱即用。
Containerization is the most common deployment method for Caddy. The official image is small (~40MB) and works out of the box.
🟢 基础 / Basics
最简 Docker 运行
docker run -d \
-p 80:80 \
-p 443:443 \
-v ./Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
-v caddy_config:/config \
caddy:2
三个挂载点:
| 挂载 | 用途 |
|---|---|
/etc/caddy/Caddyfile | 配置文件 |
/data | 证书和 ACME 状态(必须持久化) |
/config | 运行时配置缓存 |
Docker Compose 基础版
# docker-compose.yml
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
# Caddyfile
example.com {
respond "Hello from Docker!"
}
docker compose up -d
查看日志
docker compose logs -f caddy
🟡 进阶 / Intermediate
Docker Compose:Caddy + 应用
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
- app
app:
image: node:20-alpine
working_dir: /app
volumes:
- ./app:/app
command: ["node", "server.js"]
expose:
- "3000"
volumes:
caddy_data:
caddy_config:
example.com {
reverse_proxy app:3000
}
Caddy 通过 Docker 网络直接以服务名 app 访问后端。
多站点 Docker Compose
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./sites:/srv
- caddy_data:/data
- caddy_config:/config
api:
image: golang:1.22
# ...
blog:
image: wordpress:latest
# ...
volumes:
caddy_data:
caddy_config:
example.com {
reverse_proxy api:8080
}
blog.example.com {
reverse_proxy blog:80
}
static.example.com {
root * /srv/static
file_server
}
传递环境变量
services:
caddy:
image: caddy:2
environment:
- DOMAIN=example.com
- APP_PORT=3000
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
{$DOMAIN:localhost} {
reverse_proxy app:{$APP_PORT:3000}
}
{$VAR:default} 语法:读取环境变量,不存在时使用默认值。
挂载静态文件目录
services:
caddy:
image: caddy:2
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./public:/srv:ro
- caddy_data:/data
- caddy_config:/config
example.com {
root * /srv
file_server
}
自定义 Caddy 镜像(带插件)
FROM caddy:2-builder AS builder
RUN xcaddy build \
--with github.com/caddyserver/transform-encoder \
--with github.com/mholt/caddy-ratelimit
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
docker build -t my-caddy .
TLS 证书持久化
⚠️ 关键: 不持久化 /data 会导致每次重建容器时重新申请证书,可能触发 Let’s Encrypt 速率限制。
volumes:
caddy_data:
driver: local
driver_opts:
type: none
o: bind
device: /opt/caddy/data
或使用 bind mount:
volumes:
- /opt/caddy/data:/data
- /opt/caddy/config:/config
🔴 高级 / Advanced
Caddy Docker Proxy(自动发现)
lucaslorentz/caddy-docker-proxy 让 Caddy 通过 Docker label 自动生成配置:
services:
caddy:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- caddy_data:/data
webapp:
image: nginx:alpine
labels:
caddy: example.com
caddy.reverse_proxy: "{{upstreams 80}}"
api:
image: node:20
labels:
caddy: api.example.com
caddy.reverse_proxy: "{{upstreams 3000}}"
caddy.encode: gzip
无需维护 Caddyfile,所有配置来自 Docker labels。
Docker Swarm 模式
services:
caddy:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
deploy:
mode: global
placement:
constraints:
- node.role == manager
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
webapp:
image: nginx:alpine
deploy:
replicas: 3
labels:
caddy: example.com
caddy.reverse_proxy: "{{upstreams 80}}"
在 Swarm 模式下,Caddy 自动发现所有副本并进行负载均衡。
Docker 网络隔离
services:
caddy:
image: caddy:2
networks:
- frontend
- backend
ports:
- "80:80"
- "443:443"
app:
image: node:20
networks:
- backend
# 注意:app 不在 frontend 网络,无法被外部直接访问
db:
image: postgres:16
networks:
- backend
# db 只在 backend 网络
networks:
frontend:
backend:
internal: true # 不允许外部访问
Caddy 同时在 frontend 和 backend 网络中,充当中间层。
健康检查 + 重启策略
services:
caddy:
image: caddy:2
healthcheck:
test: ["CMD", "caddy", "version"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
restart: unless-stopped
多阶段构建:前端 + Caddy
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 运行阶段
FROM caddy:2
COPY --from=builder /app/dist /srv
COPY Caddyfile /etc/caddy/Caddyfile
一个镜像包含前端构建结果和 Caddy,开箱即用。
容器内 Caddy 管理
# 进入容器
docker exec -it caddy-container sh
# 查看配置
caddy list-modules
# 重载配置(容器内)
caddy reload --config /etc/caddy/Caddyfile
# 验证配置
caddy validate --config /etc/caddy/Caddyfile
多容器共享证书
使用共享 volume 让多个 Caddy 实例共享证书:
services:
caddy1:
image: caddy:2
volumes:
- shared_certs:/data
caddy2:
image: caddy:2
volumes:
- shared_certs:/data
volumes:
shared_certs:
小结 / Summary
| 层级 | 内容 |
|---|---|
| 🟢 基础 | Docker run、基本 Compose、三个挂载点 |
| 🟡 进阶 | Compose + 应用、环境变量、自定义镜像、证书持久化 |
| 🔴 高级 | caddy-docker-proxy、Swarm、网络隔离、多阶段构建 |