To expose Docker apps securely with Cloudflare Tunnel, create a Cloudflare Tunnel, run Cloudflared in Docker with the tunnel token, and route a public hostname to your app’s internal Docker port. This lets users access the app through Cloudflare without opening inbound ports on your VPS.
This setup is useful for remote access to self-hosted apps, admin dashboards, APIs, and development tools, as public traffic passes through Cloudflare rather than reaching your server directly. In this guide, you’ll learn how to install Cloudflared with Docker, run it with Docker Compose, deploy it faster using Hostinger’s Docker template, and secure the exposed app with access rules and private Docker networking.
What do you need before installing Cloudflared with Docker?
Before installing Cloudflared with Docker, prepare a running Docker app, a Cloudflare account, and a domain connected to Cloudflare. You also need access to the Cloudflare Zero Trust dashboard, where you create the tunnel and obtain the tunnel token.
Make sure you have:
- A VPS or server with Docker installed.
- A Docker app running on a local port, such as 8080.
- A Cloudflare account.
- A domain using Cloudflare nameservers.
- Access to Cloudflare Zero Trust.
- A tunnel token from Cloudflare Tunnel.
If your Docker app already runs on the server, test it before creating the tunnel:
curl http://localhost:8080
Replace 8080 with the port your app uses. If the app responds locally, Cloudflared can route traffic to it after the tunnel is created.
How to install Cloudflared with Docker
Cloudflared runs as a Docker container and connects your server to Cloudflare Tunnel. This lets Cloudflare route traffic to your Docker app without exposing the app’s port directly to the internet.
Before starting, make sure your Docker app is already running on the server. For example, if your app listens on port 8080, test it locally:
curl http://localhost:8080
If the app responds, create a Cloudflare Tunnel from the Cloudflare Zero Trust dashboard. Open Networks → Tunnels → Create tunnel, choose Cloudflared, and copy the tunnel token generated by Cloudflare.
Then, run the official Cloudflared Docker image with the token:
docker run -d --name cloudflared --restart unless-stopped cloudflare/cloudflared:latest tunnel --no-autoupdate run --token
Replace
After the container starts, verify that Cloudflared is running:
docker ps
You can also check the tunnel logs:
docker logs cloudflared
Next, add a public hostname in the Cloudflare Tunnel settings. For example, route:
app.example.com → http://localhost:8080
This tells Cloudflare to send requests from app.example.com to the Docker app running on your server. Once the hostname is active, open it in your browser and confirm that the app loads through Cloudflare Tunnel.
For better security, avoid publishing the app port with -p unless you need local access. Cloudflared only needs to reach the app from the server, while public traffic goes through Cloudflare.
How to deploy Cloudflared faster with Hostinger’s Docker template
Hostinger’s Cloudflared Docker template lets you deploy Cloudflared on a VPS without manually preparing the container from scratch. Instead of installing Docker, pulling the image, and writing the run command yourself, you can launch a preconfigured Cloudflared environment from the Hostinger VPS dashboard.
To deploy it, open your Hostinger account and go to VPS → Manage → OS & Panel → Operating system. Then, choose the Cloudflared template from the Docker templates catalog and install it on your VPS.
After the template is installed, connect to your VPS using SSH:
ssh root@your_vps_ip
Then, check whether the Cloudflared container is running:
docker ps
If the container is active, open your Cloudflare Zero Trust dashboard and create a new tunnel. Go to Networks → Tunnels → Create tunnel, choose Cloudflared, and copy the tunnel token.
Use the token to connect your Hostinger VPS to Cloudflare Tunnel. Depending on your template setup, you can either update the existing container configuration or recreate the Cloudflared container with your tunnel token:
docker run -d --name cloudflared --restart unless-stopped cloudflare/cloudflared:latest tunnel --no-autoupdate run --token
Replace
docker logs cloudflared
Once Cloudflared is connected, add a public hostname in Cloudflare Tunnel settings. For example, route your domain or subdomain to the Docker app running on your VPS:
app.example.com → http://localhost:8080
This setup is useful when you want secure remote access to Docker apps on an always-on VPS. Cloudflared handles the public connection through Cloudflare Tunnel, while your application stays behind the VPS firewall without requiring open inbound ports.
How to run Cloudflared with Docker Compose
Docker Compose is the best option when Cloudflared and your app must run on the same Docker network. This lets Cloudflared reach the app by its service name instead of exposing the app’s port publicly.
First, create a project folder:
mkdir cloudflared-app cd cloudflared-app
Then, create a .env file for your Cloudflare Tunnel token:
nano .env
Add your tunnel token to the file:
TUNNEL_TOKEN=your_cloudflare_tunnel_token
Next, create a docker-compose.yml file:
nano docker-compose.yml
Add the following configuration:
services:
app:
image: your-app-image
container_name: my-app
expose:
- "8080"
networks:
- cloudflare-tunnel
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
depends_on:
- app
networks:
- cloudflare-tunnel
networks:
cloudflare-tunnel:
Replace your-app-image with the Docker image for your application. Keep exposed instead of ports if the app only needs to be reachable by Cloudflared. This keeps the app available inside the Docker network without publishing port 8080 on the VPS.
Start both containers:
docker compose up -d
Check whether the containers are running:
docker compose ps
Then, confirm that Cloudflared is connected to Cloudflare Tunnel:
docker compose logs cloudflared
After the tunnel is active, add a public hostname in Cloudflare Tunnel settings. Since both containers use the same Docker network, route the hostname to the app service name:
app.example.com → http://app:8080
This tells Cloudflare to forward requests from app.example.com to the app service running in Docker Compose. The application does not need a public port because Cloudflared forwards traffic through the shared Docker network.
Why use Cloudflare Tunnel for secure remote access to Docker apps?
Cloudflare Tunnel lets you expose Docker apps via an outbound connection rather than opening inbound ports on your server. This gives users a public URL for the app while keeping the Docker container behind the VPS firewall.
This setup is useful for self-hosted tools that need remote access, such as admin dashboards, automation apps, monitoring panels, internal APIs, and development environments. For example, you can expose a Dockerized app like n8n, Grafana, Portainer, code-server, or a private web app without publishing its container port to the internet.
Cloudflare Tunnel improves remote access security in four main ways:
- It avoids public port forwarding. Cloudflared connects your server to Cloudflare from the inside, so you do not need to expose ports like 8080, 3000, or 9000 publicly.
- It hides the origin server IP. Visitors connect to Cloudflare first, while your VPS address stays separate from the public application URL.
- It supports hostname-based routing. You can route subdomains like app.example.com, admin.example.com, or api.example.com to different Docker services running on the same server.
- It works with Cloudflare Access. You can require login, email verification, or identity provider authentication before users reach sensitive Docker apps.
For Docker workloads, this means Cloudflared acts as a secure bridge between Cloudflare and your containers. The application stays inside the Docker network, and Cloudflare handles the public-facing connection. This is safer than exposing a container port directly because only the tunnel, not the app itself, receives external traffic.
How to secure Docker apps exposed with Cloudflare Tunnel
Cloudflare Tunnel improves Docker app security by eliminating the need for public inbound ports, but it still requires access rules, token protection, and container-level hardening. Treat Cloudflared as the public entry point to your private Docker service.
First, keep your Docker app off public ports whenever possible. If Cloudflared and the app run on the same Docker network, use expose instead of ports in your Compose file:
services: app: image: your-app-image expose: - "8080"
The expose option makes the app reachable inside Docker without publishing port 8080 on the VPS. Cloudflared can still route traffic to the app through the internal Docker network:
app.example.com → http://app:8080
Next, protect sensitive apps with Cloudflare Access. This is especially important for admin panels, dashboards, internal APIs, and tools like Portainer, Grafana, n8n, or code-server. In Cloudflare Zero Trust, create an Access application for your public hostname and define who can open it. For example, allow only specific email addresses, company domains, or users from your identity provider.
Store your tunnel token securely. Do not paste the token directly into public repositories, shared documents, or reusable scripts. Use a local .env file if you run Cloudflared with Docker Compose:
TUNNEL_TOKEN=your_cloudflare_tunnel_token
Then reference the token in your Compose file:
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
Rotate the tunnel token if it is exposed, shared with the wrong user, or stored in a place you no longer control. After rotating the token in Cloudflare, update the value on your VPS and restart the Cloudflared container:
docker compose restart cloudflared
You should also limit each public hostname to the correct internal service. For example, route app.example.com only to the app container and admin.example.com only to the admin container. Avoid using broad fallback routes that send unknown requests to sensitive services.
Finally, monitor the tunnel and container logs regularly:
docker compose logs cloudflared
Look for repeated connection failures, unexpected hostname requests, or routing errors. These logs help confirm that Cloudflared is connected, the public hostname points to the correct Docker service, and the app remains reachable only through the tunnel.
What to do after exposing your Docker app securely
After your Docker app is available through Cloudflare Tunnel, strengthen the setup before using it for regular remote access. The tunnel eliminates the need for inbound public ports, but you still need to manage authentication, updates, monitoring, and backups.
Start by adding a Cloudflare Access policy to every sensitive hostname. Public apps, documentation sites, or demo pages may stay open, but admin panels and internal tools should require authentication. For example, protect admin.example.com with an email allowlist, company domain rule, or identity provider login.
Next, confirm that the app port is not exposed publicly on the VPS. If you use Docker Compose, prefer expose instead of ports for services that only Cloudflared needs to reach:
services: app: image: your-app-image expose: - "8080"
Then, check your active firewall rules and make sure ports like 8080, 3000, or 9000 are not open unless another service needs them:
ufw status
Keep Cloudflared up to date so your tunnel receives the latest fixes. If you use the official Docker image, pull the newest version and recreate the container:
docker compose pull cloudflared docker compose up -d cloudflared
Monitor the tunnel regularly from both Cloudflare and your VPS. In Cloudflare Zero Trust, check whether the tunnel status is healthy. On the VPS, review Cloudflared logs when the app becomes unreachable:
docker compose logs cloudflared
Finally, document your tunnel configuration. Record which public hostname points to which Docker service, which ports are used internally, where the tunnel token is stored, and which Access policies protect each app. This makes future updates safer, especially when you add more Docker apps behind the same Cloudflare Tunnel.
All of the tutorial content on this website is subject to
Hostinger’s rigorous editorial standards and values.
Apply for Premium Hosting
Source Credit: https://www.hostinger.com/in/tutorials/how-to-set-up-cloudflared-with-docker
