
书接上回,如果要使用Caddy 2为多个服务提供反向代理/Web服务器的话,配置文件大概是这样
jellyfin.caddy2tutorial.tk {
reverse_proxy localhost:8096
}
hass.caddy2tutorial.tk {
reverse_proxy localhost:8123
}
www.caddy2tutorial.tk {
root * /part/to/www
file_server
} 如此配置,Caddy 2会为每个域名单独申请一个SSL证书。但是当申请的证书过多时,可能会触发Let's Encrypt的速率限制,所以就需要泛域名证书。

https://caddyserver.com/docs/automatic-https#dns-challenge
查看Caddy 2官方文档,我们发现,Caddy 2自动申请/管理/Renew泛域名证书需要DNS质询才能实现,而官方的Caddy Docker Image是不包括任何DNS质询功能的。好在官方提供了相当方便的方式构建自定义镜像。

https://caddyserver.com/download
上面是官方的Caddy 2二进制文件下载,如果你不是非得用Docker运行Caddy 2的话,那选择需要的插件然后点Download即可。但如果和我一样用着UNRAID,没有systemctl,而且还爱用Docker的话……那就自己build镜像吧。

https://hub.docker.com/_/caddy
通过很简单的Dockerfile,就可以自己构建包含社区插件的Docker镜像了。
#到 https://hub.docker.com/_/caddy/tags 查找合适的builder镜像tag
#为了更小的体积,我选择builder-alpine
FROM caddy:builder-alpine AS builder
RUN xcaddy build \
#到 https://caddyserver.com/download 寻找所需要的插件添加到此处 记得前面加上--with
#我的域名由Cloudflare提供DNS服务 所以添加caddy-dns/cloudflare插件
#顺手加上其他需要的插件 比如Webdav
--with github.com/mholt/caddy-webdav \
--with github.com/caddy-dns/cloudflare
#叠加所需的原始镜像,alpine挺好的
FROM caddy:alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy 保存为Dockerfile,运行docker build命令
docker build -t caddy-custom .
# -t 镜像标签 创建容器时需要
# 不要漏掉最后的 . 它代表以当前目录运行命令 镜像构建完成,接下来编辑Caddy 2的配置文件Caddyfile
不像文章开头的例子,新的Caddyfile需要达成两个事情
让Caddy 2使用DNS质询来创建/管理/Renew泛域名证书
使用泛域名证书
所以新的Caddyfile是这样子的
caddy2.tutorial *.caddy2.tutorial {
# 假设你有caddy2.tutorial这个域名,所有服务都将通过这个域名及它的二级域名提供访问,那么如上
# 一级/二级/三级域名的证书不通用 如果需要为三级域名申请证书 也需要添加在上面
# 泛域名证书好像只支持一个通配符*
tls {
DNS cloudflare [token]
}
# 在 tls 这个 block 设定 DNS 质询的相关参数,详情请参考每个社区插件具体的文档
@server-1 host s1.caddy2.tutorial
# 创建一个名为server-1的匹配器 他的匹配规则是请求标头的host字段(即访问的域名)为 s1.caddy2.tutorial
handle @server-1 {
reverse_proxy 10.0.0.10:8123
}
# 处理符合server-1匹配器规则的访问 提供反向代理
@server-2 host s2.caddy2.tutorial
handle @server-2 {
reverse_proxy 10.0.0.10:9090
}
@static-website host caddy2.tutorial www.caddy2.tutorial
# 可以匹配多个条件 比如两个不同的host
handle @static-website {
root * /part/to/www
file_server
}
handle {
respond 404
}
# 兜底 处理不匹配所有匹配器的访问 统一返回404错误代码
} 完成Caddyfile编辑后,就可以使用自己构建的 带有自定义社区插件的Caddy 2镜像来创建容器了。
docker run -d --name='custom-caddy' \
--network='host' \
# 使用Host网络 将所有端口直接暴露到主机上
# 根据自己的需求 可改为bridge或custom bridge
# 关于Docker Network的知识请寻找其他资料学习
-v '/part/to/caddyv2/data':'/data':'rw' \
# -v 参数为挂载,第一个冒号左侧为主机目录 右侧是容器内目录
# 最后的rw为权限 赋予容器对此目录读(r)写(w)的权限
# 证书文件默认存放在容器内/data目录下
-v '/part/to/caddyconfig/custom-caddy':'/config':'rw' \
# 由caddy自动生成的autosave.json默认存放在容器内/config目录下
-v '/part/to/Caddyfile':'/etc/caddy/Caddyfile':'rw' \
# 此处挂载的Caddyfle为「文件」而不是「目录」请先编辑好Caddyfile后再挂载
custom-caddy
# 使用我们之前构建的tag为custom-caddy的镜像来创建容器
相关文档
https://caddyserver.com/docs/caddyfile/directives/handle#handle
https://caddyserver.com/docs/caddyfile/matchers
https://hub.docker.com/_/caddy