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 frontendhttp://api.localhost→ your backendhttp://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.