Self-Hosting with Docker and Traefik, Without an Ops Team
A practical introduction to running web apps on your own infrastructure with Docker Compose and Traefik, including automatic HTTPS.
You do not need a dedicated DevOps team, or a hefty platform bill, to run production software reliably. A small server, Docker and a reverse proxy cover a surprising amount of ground. Here is the approach we reach for most often.
The building blocks
- Docker packages your application and its dependencies, so it runs the same way on your laptop, in staging and in production.
- Docker Compose describes your whole stack (app, database, cache) in one file.
- Traefik is a reverse proxy that discovers your containers, routes traffic to them by hostname and obtains HTTPS certificates automatically via Let's Encrypt.
A minimal example
This compose.yaml runs Traefik and a single web app with automatic HTTPS:
services:
traefik:
image: traefik:v3
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- [email protected]
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
app:
image: your-app: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
volumes:
letsencrypt:
Point your DNS at the server, run docker compose up -d, and Traefik requests a certificate and starts routing traffic. Adding another app is a matter of adding another service with its own labels.
What to add before calling it production
A running container is not a production system. Before you rely on it:
- Backups. Automate database and volume backups to off-server storage, and practise restoring them.
- Monitoring. At minimum, an uptime check that alerts you when the site is down.
- Updates. A routine for patching the host OS and refreshing images.
- Secrets. Keep credentials out of images and repositories; use environment files or a secrets manager.
- Firewall. Expose only ports 80 and 443 (and SSH, restricted) to the internet.
- Docker socket care. Mounting the Docker socket gives a container powerful access. Read-only helps, and a socket proxy is better still for sensitive environments.
- A runbook. Write down how to deploy, roll back and recover, so it does not live only in one person's head.
When self-hosting is the right call
It tends to pay off when you have predictable workloads, want to control costs, need data to stay in a particular place, or have outgrown the pricing of managed platforms. When your priority is zero operational involvement, a managed platform may be the better trade, and that is a legitimate choice.
Want help setting up or hardening your infrastructure? Talk to us. We build deployments small teams can actually maintain.