How to expose your Docker apps securely with Cloudflare
Self-hosting your apps at home or on a VPS is powerful — but exposing them securely to the internet can be a challenge. Public IPs, router configs, and HTTPS certificates are often a hassle. This is where Cloudflare Tunnel comes in: a secure, reliable way to expose services without opening ports or handling HTTPS yourself.
In this post, I’ll show you how to set up Cloudflare Tunnel to expose your Dockerized web apps to the internet, securely and for free.
🔒 Why Use Cloudflare Tunnel?
- No port forwarding: Avoid opening your firewall or router.
- Free HTTPS: Automatic TLS certificates via Cloudflare.
- Zero Trust controls: Protect your internal services with identity-based access.
- High availability: Cloudflare’s edge network acts as a global reverse proxy.
⚙️ Prerequisites
- A Cloudflare account
- Your domain managed by Cloudflare (e.g.
your-domain.com
) - A self-hosted server with Docker installed
- Your app running on a local port (e.g. a web app at
localhost:8080
)
🛠️ Step-by-Step Setup
1. Install cloudflared
Download the Cloudflare Tunnel client:
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
Or via package manager:
sudo apt install cloudflared
2. Authenticate with Cloudflare
Run:
cloudflared tunnel login
This opens a browser and lets you authorize the tunnel for your domain.
3. Create the Tunnel
cloudflared tunnel create my-tunnel
This creates a tunnel ID and credentials in ~/.cloudflared/
.
4. Create the Config File
Create ~/.cloudflared/config.yml
:
tunnel: my-tunnel
credentials-file: /home/youruser/.cloudflared/my-tunnel.json
ingress:
- hostname: your-domain.com
service: http://localhost:8080
- service: http_status:404
This maps the public domain (your-domain.com
) to your internal app (localhost:8080
).
5. Add a CNAME Record
In your Cloudflare DNS dashboard:
- Type: CNAME
- Name:
app
- Target:
your-tunnel-id.cfargotunnel.com
- Proxy status: Proxied (orange cloud)
Alternatively, run:
cloudflared tunnel route dns my-tunnel app.eztalo.com
6. Run the Tunnel
Start it manually:
cloudflared tunnel run my-tunnel
Or run as a service:
sudo cloudflared service install
sudo systemctl enable --now cloudflared
🐳 Bonus: Using with Docker Compose
Run cloudflared
in a sidecar container:
# docker-compose.yml
services:
web:
image: myapp
ports:
- "8080:80"
tunnel:
image: cloudflare/cloudflared:latest
command: tunnel run
environment:
- TUNNEL_TOKEN=<your-tunnel-token>
restart: unless-stopped
To get the TUNNEL_TOKEN
, run:
cloudflared tunnel token my-tunnel
✅ Verify Everything Works
Visit https://your-domain.com
in your browser. Your Docker app should be live, secured with HTTPS, and accessible anywhere — without exposing your home network or VPS ports.
🔐 Optional: Secure with Cloudflare Zero Trust
Add an identity-based access rule:
- Go to Cloudflare Zero Trust Dashboard
- Create an Access Policy for your hostname (e.g.
your-domain.com
) - Require users to log in with Google, GitHub, or email
This is perfect for internal dashboards and tools.
🧠 Final Thoughts
Cloudflare Tunnel is a powerful and easy way to make your self-hosted Docker apps securely available to the internet. Whether you’re hosting dashboards, dev tools, or full-blown web apps — it saves you time, hassle, and makes things just work.