A Cloudflare Tunnel removes inbound port exposure, but it does not remove the need to design ingress. The failure mode I keep seeing is treating “tunnel connected” as proof that the application is healthy. There are actually four independently failing hops:

  1. DNS and edge: the hostname resolves, proxying is enabled, and TLS covers the name.
  2. Tunnel: at least one authenticated cloudflared connector is connected.
  3. Ingress: the ordered hostname/path rule selects the intended Docker service.
  4. Origin: the container is ready and its dependencies can serve a representative request.

A few production rules that follow from that model:

  • Put cloudflared on a narrow private Docker network and route to Compose service names, not localhost or fixed container names.
  • End ingress with an explicit http_status:404 catch-all so an unknown hostname cannot fall through to an application.
  • Monitor connector health and origin readiness separately. A healthy origin behind a disconnected connector is unavailable; a connected tunnel pointing to a failed origin is also unavailable.
  • Treat credentials as infrastructure secrets, pin the connector image, and document rotation rather than baking a token into the image or command line.
  • Verify an actual public content page after every route change. HTTP 200 alone can be a parking page or the wrong container.
  • Multiple connectors on one host do not eliminate the host, ISP, or power circuit as a single point of failure.

I turned the full setup, release sequence, and rollback checks into a detailed guide: https://blog.gask.co.in/articles/cloudflare-tunnel-docker-production-checklist

Disclosure: this is my article. What checks do you use to distinguish edge, connector, ingress, and origin failures in your own setup?

submitted by /u/canibal_
[link] [留言]