Comparing Traefik and Caddy for HTTPS routing in Docker environments

By · Published on · Updated on · 7 min read

Colorful shipping containers forming arcs against a blue sky
Clean, symbolic composition for containers and Docker orchestration Photo: Jan van der Wolf / Pexels

This comparison of Traefik vs Caddy for HTTPS routing in Docker focuses on what matters to DevOps teams: automatic discovery, Let's Encrypt TLS, middlewares, metrics and operations. You’ll see practical differences, minimal examples and clear criteria to decide which fits your stack.

Scope and usage profiles

The focus is HTTP/HTTPS routing, TLS termination and load balancing for multiple containers on a Docker host. Kubernetes is out of scope. The analysis emphasizes automation, operational simplicity and extensibility.

Typical profiles: teams using Docker Compose, Portainer or custom orchestration that want automatic HTTPS with minimal rework. If you are still assembling the environment, review how to install Docker and Compose first.

Common prerequisites: DNS pointed to the server, ports 80/443 open and a Docker network shared between the proxy and apps.

  • Teams hosting many services per host and multiple distinct domains.
  • CI/CD environments that recreate containers frequently.
  • Need for reliable metrics and logs for troubleshooting.
  • Requirement for HTTP/2 and HTTP/3/QUIC to reduce latency.

Configuration and service discovery in Docker

The main difference lies in the configuration model and service discovery from Docker. Traefik has a native Docker provider with label-based routing. Caddy uses Caddyfile/JSON; for automatic discovery via labels it's common to use a plugin (e.g., caddy-docker-proxy) or a config generator.

If you prefer declaring everything in the compose file with labels and getting immediate reloads when containers start/stop, Traefik is usually more straightforward. If you want a single, human-readable rules file, the Caddyfile is very appealing.

Aspect Traefik Caddy
Docker discovery Native via labels (Docker provider) Via Caddyfile/JSON; automatic discovery requires a plugin/generator
Config style Static + dynamic (YAML/TOML + labels) Caddyfile simple or JSON via admin API
Hot reload Docker events and files (no downtime) Reload via API/CLI; Caddyfile is easy to review
Plugins Ecosystem of middlewares and providers Strong ecosystem; many features via modules
Learning curve Labels and concepts of routers/services/middlewares Caddyfile DSL is concise and readable

Automatic HTTPS and certificate management

Both automate certificates with ACME/Let's Encrypt. Traefik integrates resolvers and stores the certificate bundle in a file/volume. Caddy also issues and renews automatically; storage is local by default and configurable.

Common ACME challenges: HTTP‑01 and TLS‑ALPN‑01 are supported by both. For DNS‑01, Traefik offers integrations; in Caddy DNS‑01 requires a DNS provider module. Make sure DNS, ports 80/443 and system clock are correct to avoid failures.

If you need to understand Let's Encrypt basics, consult an introductory guide before deploying the proxy.

  • Per-domain TLS and SANs with automatic renewal.
  • HTTP→HTTPS redirects and configurable HSTS.
  • SNI for multiple hosts on the same IP.
  • HTTP/2 and HTTP/3/QUIC available.

Routing, middlewares and load balancing

Traefik supports routing by host, path, headers, methods and more, with built-in middlewares (rate limiting, compression, headers, forward auth). Caddy has powerful matchers and handlers in the Caddyfile; many advanced features come via modules.

For load balancing, both support multiple backends and weight policies. TLS passthrough is native in Traefik; in Caddy, L4 features and passthrough require a specific module. Complex transformations can impact throughput.

  • Rewrites, strip_prefix and redirects.
  • Security headers and CSP via middlewares/handlers.
  • Basic auth and SSO integration via forward-auth.
  • Canary/blue‑green by assigning weights per service.

Observability, logs and troubleshooting

Traefik exports Prometheus metrics natively and provides structured access logs. Caddy exposes detailed logs and can export metrics via a Prometheus module. Both integrate well with observability stacks running in Docker.

To monitor latency, error rates and certificates, integrate with Prometheus and Grafana. Structured logs help trace correlations using a request-id. Do not keep metrics without retention — that harms RCA.

  • Metrics: P95/P99 latency, 5xx rate, traffic per host.
  • Access logs with useful fields (host, path, upstream, timing).
  • Active health checks to avoid sending traffic to bad backends.
  • Distributed tracing via middlewares/plugins when applicable.

Quick example: Traefik with Docker labels (automatic HTTPS)

Minimal example with Traefik 2.x and an app container. Replace the domain and ensure DNS and ports 80/443 are open. The certResolver uses ACME for Let's Encrypt and persists to a volume. Useful with Docker Compose.

If you're getting started with Docker/Compose, review installation and best practices before running in production.

version: "3.8"

services:
  traefik:
    image: traefik:v2.10
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - [email protected]
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.le.acme.httpchallenge=true
      - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
      - --api.dashboard=true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_letsencrypt:/letsencrypt
    labels:
      - "traefik.enable=true"

  app:
    image: yourorg/yourapp:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`app.example.com`)"
      - "traefik.http.routers.app.entrypoints=websecure"
      - "traefik.http.routers.app.tls.certresolver=le"
      - "traefik.http.services.app.loadbalancer.server.port=3000"

volumes:
  traefik_letsencrypt: {}

Quick example: Caddy with Caddyfile + Docker

Caddy issues and renews certificates automatically. In the example, a simple Caddyfile proxies to the "app" container on a shared network. For automatic discovery by labels, use a suitable module. Make sure your firewall is reviewed and the domain resolves to the host.

version: "3.8"

services:
  caddy:
    image: caddy:2
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

  app:
    image: yourorg/yourapp:latest
    expose:
      - "3000"

volumes:
  caddy_data: {}
  caddy_config: {}

# Caddyfile (salve ao lado do compose)
# app.example.com {
#   reverse_proxy app:3000
# }

Quick selection criteria and trade-offs

If your workflow is label-oriented in Docker and you want immediate discovery without plugins, Traefik usually fits better. If you value a readable configuration file that's easy to version, the Caddyfile is a strong advantage.

In environments that demand out‑of‑the‑box Prometheus metrics and built-in rate limiting, Traefik leads. For complex HTTP scenarios with short, clear rules, Caddy simplifies PR review and readability.

Other traditional configuration options such as Nginx may be worth comparing to understand trade-offs with classic proxies.

  • Choose Traefik when: Compose labels are standard, you need a native Docker provider, immediate Prometheus metrics and TLS passthrough without plugins.
  • Choose Caddy when: you want a clear Caddyfile, mature HTTP/3 support, on‑demand modules and readable HTTP rules for code review.
  • Both are production-ready; your team's tooling and operational practices should guide the decision.

Frequently asked questions

Is Traefik or Caddy simpler for Docker Compose?

If you prefer declaring routing via labels inside docker-compose, Traefik is generally more straightforward. If you want to centralize rules in a human‑readable file, the Caddyfile greatly simplifies review and versioning.

Do both handle Let's Encrypt automatically?

Yes. Traefik and Caddy automate issuance and renewal via ACME. Use HTTP‑01 or TLS‑ALPN‑01. For DNS‑01, Traefik offers integrations; in Caddy you need to add the DNS provider module. Ensure DNS and ports 80/443 are open.

Do they support HTTP/3 (QUIC)?

Yes. Both Traefik and Caddy support HTTP/3/QUIC. Check client, OS and network compatibility. If there are intermediate proxies, HTTP/3 may fall back to HTTP/2, which still delivers latency improvements.

Can I reload configuration without dropping connections?

Yes. Both support dynamic configuration reloads. Traefik reacts to Docker events and file changes. Caddy applies changes via API/CLI or by reloading the Caddyfile, keeping connections active when possible.

How do I expose metrics for Prometheus?

Traefik exports Prometheus metrics natively. In Caddy, enable the Prometheus metrics module. In both cases, scrape with Prometheus and visualize in Grafana to monitor latency, errors and per‑host traffic.

Can I use TLS passthrough?

Traefik supports TLS passthrough natively. In Caddy, this requires a specific L4 module. Use passthrough only when you need to route TLS without termination, as it limits HTTP inspection and higher‑level features.

Need to decide between Traefik and Caddy for your Docker?

Describe your scenario, domains and observability requirements. We can quickly evaluate fit, risks and a safe migration path.

Discuss your stack

See also