Skip to main content
Simplifying Local Environments with Docker Compose and Traefik
  1. Blog Posts/

Simplifying Local Environments with Docker Compose and Traefik

2 min read·
docker fullstack traefik

Published on: 2021-09-15

Working on multiple projects locally can get messy—conflicting ports, hardcoded hostnames, clashing environments. Docker helps, but managing dozens of services and remembering which port maps to which project? That’s where the pain really starts.

Enter Docker Compose and Traefik: together, they make local dev environments scalable, isolated, and easy to use.

🧩 The Problem

You’ve probably done this:

localhost:3000  # React frontend
localhost:8000  # Laravel API
localhost:5432  # Postgres

Until you start another project and forget which port is which. Or two projects want the same port. Or you want to access http://myproject.local instead of typing ports like a robot.

This is where Traefik shines.

🧭 What Is Traefik?

Traefik is a modern reverse proxy and load balancer designed for microservices. It can automatically detect containers spun up by Docker Compose, assign them domains like project.localhost, and route traffic accordingly—all with zero manual config.

Think of it like an automatic NGINX + DNS + SSL (yes, even locally).

🗂️ Project Structure

Let’s say we have two projects: webapp and api. Each has its own Dockerfile. We’ll use one Traefik container to manage them.

Directory Layout:

.
├── docker-compose.yml
├── traefik/
│   └── traefik.yml
├── webapp/
│   └── Dockerfile
└── api/
    └── Dockerfile

⚙️ Traefik Config (traefik/traefik.yml)

entryPoints:
  web:
    address: ":80"

providers:
  docker:
    exposedByDefault: false

🛠️ Docker Compose (docker-compose.yml)

version: "3.8"

services:
  traefik:
    image: traefik:v2.5
    command:
      - --api.insecure=true
      - --providers.docker=true
      - --entrypoints.web.address=:80
    ports:
      - "80:80"
      - "8080:8080" # Traefik dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  webapp:
    build: ./webapp
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`webapp.localhost`)"
    networks:
      - default

  api:
    build: ./api
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.localhost`)"
    networks:
      - default

🌐 Accessing the Apps

After docker-compose up, you can now visit:

  • http://webapp.localhost → your frontend
  • http://api.localhost → your backend
  • http://localhost:8080 → Traefik dashboard (monitor all routes)

No port numbers. No NGINX. No /etc/hosts hacks.

⚡ Bonus: .env for Custom Domains

Allow each developer to define project-specific domains:

WEBAPP_DOMAIN=webapp.localhost
API_DOMAIN=api.localhost

Use in Compose labels:

labels:
  - "traefik.http.routers.webapp.rule=Host(`${WEBAPP_DOMAIN}`)"

🧾 Summary

Docker Compose and Traefik turn your local machine into a mini cloud. Instead of fighting ports and configs, you get readable URLs, automatic routing, and scalable environments. It’s especially powerful when juggling multiple services or teams.

If you’re still doing manual port mapping, it might be time to simplify—and let Traefik do the heavy lifting.