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:

  1. Backups. Automate database and volume backups to off-server storage, and practise restoring them.
  2. Monitoring. At minimum, an uptime check that alerts you when the site is down.
  3. Updates. A routine for patching the host OS and refreshing images.
  4. Secrets. Keep credentials out of images and repositories; use environment files or a secrets manager.
  5. Firewall. Expose only ports 80 and 443 (and SSH, restricted) to the internet.
  6. 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.
  7. 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.

Want help applying this to your project?

Tell us what you are trying to build. You will get a straight answer from the person who would actually do the work.

Start a conversation