概述
你跑了一个Docker容器,想通过域名从外网访问。传统做法是装Nginx、配反代、搞SSL证书、写rewrite规则……每一步都可能出错。
Caddy把这个流程砍到了三步:安装、写一行配置、启动。它会自动申请和续期Let’s Encrypt证书,HTTP直接跳转HTTPS,连端口都不用管。
这篇文章用Docker方式部署Caddy,配一个最简单的反代示例。
准备工作
- 一台VPS(Ubuntu 22.04+ / Debian 12+)
- 一个指向服务器IP的域名(比如
app.example.com) - Docker已安装(没装的话跑一遍
curl -fsSL https://get.docker.com | sudo sh) - 80端口和443端口未被占用
步骤
第一步:创建Caddy数据目录
sudo mkdir -p /etc/caddy
sudo chown -R $USER:$USER /etc/caddy
Caddy需要把这些目录存证书、日志和配置文件。
第二步:写Caddyfile
在 /etc/caddy/Caddyfile 写入以下内容:
app.example.com {
reverse_proxy localhost:3000
}
这里 localhost:3000 是你的应用地址。如果应用跑在另一个Docker容器里,改成容器名或内网IP:
app.example.com {
reverse_proxy my-app:3000
}
就这么简单。没有server块,没有ssl指令,没有rewrite。
第三步:用Docker启动Caddy
docker run -d \
--name caddy \
--restart unless-stopped \
-p 80:80 \
-p 443:443 \
-v /etc/caddy/Caddyfile:/etc/caddy/Caddyfile:ro \
-v caddy_data:/data \
-v caddy_config:/config \
caddy:latest
启动后Caddy会自动监听80端口,检测到域名解析正确后向Let’s Encrypt申请证书。首次申请可能需要等30秒左右。
第四步:验证HTTPS是否生效
curl -I https://app.example.com
看到这些响应头就说明一切正常:
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff
也可以直接在浏览器打开 https://app.example.com,看地址栏有没有小锁标志。
第五步:加个路径前缀(可选)
如果你的应用本身带了 /api 之类的路径前缀:
app.example.com {
reverse_proxy /api/* localhost:3000
reverse_proxy /* localhost:8080
}
或者用 handle_path 去掉前缀再转发:
app.example.com {
handle_path /api/* {
reverse_proxy localhost:3000
}
}
验证
完整检查清单:
# 1. Caddy容器是否在运行
docker ps | grep caddy
# 2. HTTP是否自动跳转HTTPS
curl -I http://app.example.com | head -5
# 3. 证书过期时间
echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null | openssl x509 -noout -dates
# 4. 查看Caddy日志
docker logs caddy --tail 20
第2步应该返回 301 Moved Permanently,Location指向HTTPS地址。第3步显示证书有效期约90天,Caddy会在到期前自动续期。
常见问题
Q: 域名还没解析到服务器IP,能用吗?
不能。Caddy申请证书前会验证域名ownership,DNS必须已经指向你的服务器。否则日志里会出现 authorization failed。
Q: 容器重启后证书还在吗?
在。证书存在 caddy_data 这个Docker volume里,不会随容器删除。但如果你删了volume,就得重新申请。
Q: 想自定义证书怎么办?
app.example.com {
tls /etc/caddy/cert.pem /etc/caddy/key.pem
reverse_proxy localhost:3000
}
挂载你自己的证书文件就行。不过大多数场景没必要,自动申请更方便。
Q: 怎么加IP限制或速率限制?
app.example.com {
@blocked ip 10.0.0.0/8
respond @blocked 403
@slow ip 10.0.0.0/8
limit_rate @slow {
bandwidth 10M
connections 10
}
reverse_proxy localhost:3000
}
Caddy内置了这些功能,不需要额外模块。
Q: 配置文件改完怎么生效?
docker restart caddy
或者不重启容器,让Caddy热加载:
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
Caddy值得每个跑服务的人试一次。它的理念就是「你只需要告诉它转发的目标,剩下的它自己处理」。配好一行之后,证书、HTTPS、HTTP跳转全都不用管了。
你的站点用的什么反代?还在手动搞Nginx证书吗?