侧边栏壁纸
博主头像
Setyg的博客

当秋风染红落叶的时候,就是新生~

  • 累计撰写 86 篇文章
  • 累计创建 66 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Caddy2 Docker Compose部署

Setyg
2026-09-08 / 0 评论 / 0 点赞 / 6 阅读 / 0 字

Caddy2 简介

Caddy 2 是一款用 Go 语言编写的、企业级开源 Web 服务器,其最突出的特性是默认开启自动 HTTPS。相比 Nginx、Apache 等传统 Web 服务器,Caddy2 在证书管理、配置简洁性和开发体验上有显著优势。

官方站点:https://caddyserver.com

核心特性

特性说明
自动 HTTPS默认开启,自动申请/续期 Let's Encrypt / ZeroSSL 证书,自动 HTTP→HTTPS 重定向
Caddyfile 配置人类可读的简洁配置格式,几行即可完成反向代理+HTTPS
JSON 配置 + Admin API完整的 JSON 结构化配置,支持通过 API 动态修改
反向代理一等公民支持,含负载均衡、健康检查、Header 操作、多传输层
零停机重载caddy reload 不中断连接即可应用新配置
高性能Go 编写,生产级性能,支持 gzip/zstd 压缩
插件扩展Go Module 插件体系,可自定义指令、Handler、TLS Provider

Caddyfile 配置语法

Caddyfile 是 Caddy2 原生的配置格式,简洁且表达力强。

静态文件服务

example.com {
    root * /var/www/html
    file_server
}

反向代理

example.com {
    reverse_proxy localhost:8080
}

仅需这两行,Caddy 就会自动为 example.com 申请证书并反向代理到 8080 端口。

多路径路由

example.com {
    handle /api/* {
        reverse_proxy localhost:3000
    }

    handle /static/* {
        root * /var/www
        file_server
    }

    handle /* {
        reverse_proxy localhost:8080
    }
}

带负载均衡的反向代理

example.com {
    reverse_proxy localhost:3000 localhost:3001 localhost:3002 {
        lb_policy round_robin
        health_uri /health
        health_interval 10s
    }
}

负载均衡策略:round_robin(轮询,默认)、least_conn(最少连接)、random(随机)、ip_hash(IP哈希)、uri_hash(URI哈希)

自动 HTTPS 详解

Caddy2 是唯一默认开启自动 HTTPS 的主流 Web 服务器。

  1. Caddy 启动时扫描配置中所有域名
  2. 对合格域名自动通过 ACME 协议向 CA(Let's Encrypt / ZeroSSL)申请证书
  3. 自动配置 TLS 并将 HTTP 请求重定向到 HTTPS
  4. 证书到期前自动续期(默认提前约 30 天)

按需 TLS(On-Demand TLS)

对于运行时才知道的域名(如 SaaS 多租户场景),可启用按需证书:

{
    on_demand_tls {
        ask http://localhost:5555/check
    }
}

:443 {
    tls {
        on_demand
    }
    reverse_proxy localhost:8080
}

内部 CA(开发/内网)

https://localhost {
    tls internal
    reverse_proxy localhost:8080
}

使用 Caddy 自签名 CA 签发证书,适合本地开发。

Docker Compose 部署

基础 Docker 运行

docker run -d \
    --name caddy \
    -p 80:80 \
    -p 443:443 \
    -v caddy_data:/data \
    -v caddy_config:/config \
    -v $PWD/Caddyfile:/etc/caddy/Caddyfile:ro \
    caddy:2

信息

/data 目录存放 TLS 证书,必须持久化,否则容器重启会重新申请证书,可能触发速率限制!

Docker Compose 单服务部署

创建 docker-compose.yaml:

services:
  caddy:
    image: caddy:2
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - webnet

  app:
    image: myapp:latest
    container_name: app
    restart: unless-stopped
    expose:
      - "3000"
    networks:
      - webnet

volumes:
  caddy_data:
  caddy_config:

networks:
  webnet:

对应 Caddyfile:

example.com {
    reverse_proxy app:3000
}

提示

在 Docker 网络中,Caddy 直接用服务名 app 作为主机名即可访问。

Docker Compose 多服务反向代理

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
    networks:
      - webnet

  frontend:
    image: my-frontend:latest
    expose:
      - "80"
    networks:
      - webnet

  api:
    image: my-api:latest
    expose:
      - "3000"
    networks:
      - webnet

  blog:
    image: my-blog:latest
    expose:
      - "8080"
    networks:
      - webnet

volumes:
  caddy_data:
  caddy_config:

networks:
  webnet:

Caddyfile:

example.com {
    handle /api/* {
        reverse_proxy api:3000
    }

    handle /blog/* {
        reverse_proxy blog:8080
    }

    handle /* {
        reverse_proxy frontend:80
    }
}

自定义 Caddy 镜像(含插件)

当需要 DNS 挑战插件(如 Cloudflare、Route53)时,需自定义构建:

FROM caddy:2-builder AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare

FROM caddy:2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

使用 xcaddy 工具编译含插件的 Caddy,适用于 DNS 挑战方式申请证书(无需开放 80 端口)。

反向代理深入

健康检查

主动健康检查:

reverse_proxy localhost:8080 {
    health_uri /health
    health_interval 10s
    health_timeout 5s
    health_status 200
}

被动健康检查:

reverse_proxy localhost:8080 {
    fail_duration 30s
    max_fails 3
    unhealthy_status 500 502 503
}

Header 操作

reverse_proxy localhost:8080 {
    # 添加/修改请求头
    header_up X-Real-IP {remote_host}
    header_up X-Forwarded-Proto {scheme}

    # 删除响应头
    header_down -Server

    # 设置响应头
    header_down X-Frame-Options DENY
}

传输层配置

reverse_proxy localhost:8080 {
    transport http {
        tls
        keep_alive 30s
        compression off
        versions 1.1 2
    }
}

Admin API

Caddy2 内置 RESTful 管理 API,默认监听 localhost:2019。

# 查看当前配置
curl localhost:2019/config/

# 更新配置(零停机)
curl localhost:2019/load \
    -X POST \
    -H "Content-Type: application/json" \
    -d @caddy.json

# 重载 Caddyfile
caddy reload

# 停止
curl localhost:2019/stop

常用场景配置

WebSocket 代理

ws.example.com {
    reverse_proxy localhost:4000
}

Caddy2 自动支持 WebSocket 代理,无需额外配置。

SPA 应用 + API 代理

app.example.com {
    root * /srv/spa/dist
    file_server

    @notStatic {
        not path /api/*
        not path *.js *.css *.png *.jpg *.svg *.ico *.woff2
    }
    rewrite @notStatic /

    handle /api/* {
        reverse_proxy api:3000
    }
}

内网服务 TLS 加密

https://internal.local {
    tls internal
    reverse_proxy localhost:8080
}

与 Nginx 对比

对比项Caddy2Nginx
自动 HTTPS✅ 默认开启❌ 需 Certbot 手动配置
配置语法Caddyfile(简洁)nginx.conf(繁琐)
动态配置Admin API 原生支持需 reload / OpenResty
语言GoC
插件Go ModuleC 模块(编译)
负载均衡内置内置(更成熟)
社区生态中等非常成熟
适合场景中小规模、HTTPS优先、Docker 友好大规模、高性能、复杂路由

常见问题

Q: 证书申请失败?

检查 80/443 端口是否开放,域名 DNS 是否正确指向服务器,是否有防火墙拦截。

Q: Docker 中证书持久化?

必须将 /data 目录挂载到 Docker Volume 或宿主机目录,否则容器重启后证书丢失。

Q: 非 80/443 端口能否自动 HTTPS?

不能。ACME HTTP-01 验证要求 80 端口可达;TLS-ALPN-01 要求 443 端口可达。内网环境用 tls internal。

参考资源

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区