Reverse Proxy, Subdomains, and Local Certificates
Port conflicts between projects, missing HTTPS in development, and confusing hostnames are classic pain points in team Docker networking. With Traefik as a central reverse proxy, mkcert for local HTTPS certificates, and cleanly isolated Docker networks, these problems can be solved once and for all.
Table of Contents
- 1. Docker Networking: Basics and Network Types
- 2. Network Isolation Between Projects
- 3. Service Discovery in Docker Compose
- 4. Avoiding Port Conflicts
- 5. Traefik as a Central Reverse Proxy
- 6. Local Subdomains with /etc/hosts and dnsmasq
- 7. Local HTTPS Certificates with mkcert
- 8. Running Multiple Projects at Once with Traefik
- 9. Networking Approaches Compared
- 10. Summary
- 11. FAQ
1. Docker Networking: Basics and Network Types
Docker Networking is the system that determines how containers communicate with each other and with the outside world. During installation, Docker automatically creates three default networks: bridge, host, and none. Docker Networking via the default bridge network connects containers on the same host, but it offers no service discovery by name: containers must communicate via IP addresses, which can change with every restart. That makes the default bridge network unsuitable for any serious application.
User-defined bridge networks solve this problem: containers on the same user-defined network can reach each other by their container name or service name in Docker Compose. That is the foundation of working Docker Networking in Compose projects. Host network mode connects the container directly to the host's network: no Network Address Translation (NAT), no port forwarding, but also no isolation. On Linux, this delivers the best performance for applications that handle many connections, such as reverse proxies or high-throughput databases.
The overlay network is designed for multi-host environments and is used in Docker Swarm or Kubernetes. It lets containers on different hosts communicate as if they were on the same network. For local development and simple single-host production environments, the bridge network is the right choice. Understanding these basics is a prerequisite for clean Docker Networking in practice.
2. Network Isolation Between Projects
In Docker Compose, every project creates its own network by default, named <projectname>_default. Containers from different projects therefore cannot reach each other by hostname, which is an important security property of Docker Networking. Problems arise when services from different projects need to communicate, for example when a monitoring stack needs to observe containers from multiple projects. The solution is a shared external network that both Compose files reference.
Network isolation in Docker Networking also has security implications: a compromised container in one project cannot, by default, access services in other projects. Anyone who wants to protect databases, caches, or internal APIs from accidental access by other containers should run those services exclusively on internal networks with no port exposure. Combining project-specific networks for internal communication with a shared reverse proxy network for external access is the most proven pattern for professional Docker Networking.
# Create a shared external network for the reverse proxy
docker network create proxy-network
# docker-compose.yml: project with internal and external network
services:
web:
image: nginx:alpine
networks:
- proxy-network # shared with Traefik for external access
- internal # project-internal communication
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.localhost`)"
db:
image: postgres:16
networks:
- internal # not exposed to proxy, internal only
environment:
POSTGRES_PASSWORD: secret
redis:
image: redis:7-alpine
networks:
- internal # Only accessible within this project
networks:
proxy-network:
external: true # Must be created before: docker network create proxy-network
internal:
driver: bridge
internal: true # No outbound internet access, fully isolated
3. Service Discovery in Docker Compose
Service discovery is one of the most practical features of Docker Networking in Compose projects. Containers on the same network can reach each other via the service name defined in the Compose file, not via IP addresses. In practice this means a PHP container connects to db:3306 instead of an IP address, and an Nginx container forwards requests to php-fpm:9000. These names are resolved internally by an embedded DNS server that Docker provides for every user-defined network.
An important detail about Docker Networking and service discovery: if a service in a Compose file is given an alias, it becomes reachable under that alias. This is useful when several projects use the same service name but need to be reachable under different hostnames, for example two Magento instances that both use db as their service name but run in separate project networks. Network aliases solve this problem elegantly without having to rename any containers.
4. Avoiding Port Conflicts
Port conflicts are one of the most common problems in Docker Networking for teams working on several projects at once. If three projects each try to bind port 80 and 443, the second and third project fail to start. The obvious fix, giving each project a different port, leads to URLs like localhost:8081 and localhost:8082, which are hard to remember and cannot realistically simulate HTTPS. The real solution is a central reverse proxy that holds port 80 and 443 and forwards requests to the correct project based on the hostname.
Without a reverse proxy, the recommendation for Docker Networking is to expose service ports only within the internal network, not bind them to the host. In the Compose file that means using expose: "80" instead of ports: "80:80". Containers on the same network can still reach the port, but the host port stays free. This prevents conflicts between projects and forces external access through the reverse proxy.
5. Traefik as a Central Reverse Proxy
For team-oriented Docker Networking, Traefik is the most compelling reverse proxy solution. The key difference from Nginx: Traefik automatically discovers new containers through the Docker API and configures itself based on container labels. No restart, no reload, and no manual configuration change is needed when a new project starts up. The Traefik process runs permanently and watches for new containers with matching labels on the shared proxy network.
Configuring Traefik for local Docker Networking is manageable: a single Compose stack for Traefik itself, joined to the shared proxy network, mounting the Docker socket, and exposing the dashboard UI on an internal port. Every project service then gets labels that tell Traefik which hostname the service should be reachable under, whether HTTPS is active, and which middleware to apply. Middleware for basic authentication, HTTP-to-HTTPS redirects, and rate limiting are all available as ready-made Traefik components.
# traefik/docker-compose.yml: central Traefik reverse proxy
services:
traefik:
image: traefik:v3.2
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=proxy-network"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Load TLS certificates from /certs directory
- "--providers.file.directory=/certs"
- "--providers.file.watch=true"
ports:
- "80:80"
- "443:443"
- "8080:8080" # Traefik dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/certs:ro
networks:
- proxy-network
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.localhost`)"
- "traefik.http.routers.dashboard.service=api@internal"
networks:
proxy-network:
external: true
6. Local Subdomains with /etc/hosts and dnsmasq
Local subdomains are the step that really make Docker Networking pleasant for teams: instead of localhost:8080, projects become reachable at myapp.localhost, shop.localhost, or api.localhost. For simple cases, a single entry in /etc/hosts is enough: 127.0.0.1 myapp.localhost. The downside is that every developer has to maintain this file manually, and wildcards like *.localhost are not supported.
The more elegant solution for Docker Networking with subdomains is dnsmasq: a local DNS server that resolves all requests for *.localhost to 127.0.0.1. On macOS, dnsmasq can be installed via Homebrew; on Linux, it is available in most distributions. Once configured, all subdomains work automatically without editing /etc/hosts. Modern browsers resolve *.localhost to 127.0.0.1 without dnsmasq, but other tools like curl and many development utilities do not; dnsmasq closes that gap.
7. Local HTTPS Certificates with mkcert
HTTPS in the local development environment is not a luxury but a necessity: cookies with the Secure flag, service workers, WebAuthn, and HTTP/2 only work over HTTPS. Docker Networking for a team therefore needs to support HTTPS, and with certificates the browser considers trustworthy. Self-signed certificates trigger browser warnings that get ignored in day-to-day work, until someone forgets to add an exception and wonders why the application will not load.
mkcert is the tool of choice for local HTTPS in Docker Networking setups. It creates a local Certificate Authority (CA) and installs it in the system truststore as well as the truststores of Chrome, Firefox, and other browsers. Certificates issued with this CA are accepted by the browser as trustworthy without any warning. A single command creates a certificate for any number of domains and wildcards: mkcert "*.localhost" "localhost" "127.0.0.1". The resulting certificate is loaded into Traefik and then applies to all subdomains.
# Install mkcert (once per developer machine)
# macOS: brew install mkcert
# Linux: see https://github.com/FiloSottile/mkcert
# Install the local CA into browser/system truststores
mkcert -install
# Generate wildcard certificate for all *.localhost subdomains
mkcert -key-file ./traefik/certs/local-key.pem \
-cert-file ./traefik/certs/local-cert.pem \
"*.localhost" "localhost" "127.0.0.1"
# Traefik TLS configuration file (./traefik/certs/tls.yml)
# tls:
# certificates:
# - certFile: /certs/local-cert.pem
# keyFile: /certs/local-key.pem
# Project service labels for HTTPS routing
# Add to any service in any docker-compose.yml:
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.myapp-secure.rule=Host(`myapp.localhost`)"
# - "traefik.http.routers.myapp-secure.entrypoints=websecure"
# - "traefik.http.routers.myapp-secure.tls=true"
8. Running Multiple Projects at Once with Traefik
The final goal of professional Docker Networking for teams is running multiple projects on the same developer machine at once, without conflicts. With Traefik as the reverse proxy, mkcert for HTTPS, and dnsmasq for subdomains, the setup looks like this: Traefik runs permanently and manages port 80 and 443. Every project has its own Compose file and its own networks for internal communication, while also joining the shared proxy network. New projects simply start up; Traefik detects them automatically and forwards requests based on the hostname.
An important aspect of Docker Networking for teams: the Traefik configuration and the shared proxy network should be maintained in a separate repository or as part of a team onboarding script. New developers run a single setup script that starts Traefik, creates the proxy network, installs mkcert, and adds the CA to the truststore. After that, they can clone and start any project repository without needing to know any further networking configuration.
| Approach | Port Conflicts | HTTPS Locally | Multiple Projects |
|---|---|---|---|
| Direct port mapping | Frequent | Not possible | Manual, cumbersome |
| Nginx as proxy | Low | Manual | Restart on change |
| Traefik + mkcert | None | Automatic | Automatic via labels |
| /etc/hosts only | Low | Browser warnings | Manual entries |
9. Networking Approaches Compared
Choosing the right Docker Networking strategy depends on team size, the number of projects active at once, and how closely the development environment needs to match production. A solo developer with a single project can get by with direct port mapping. A team of five developers actively working on six projects needs the full Traefik, mkcert, and dnsmasq infrastructure.
The critical criterion for Docker Networking is fidelity to production: the closer the local development environment resembles the production environment, the less often errors occur that cannot be reproduced locally. Enforcing HTTPS locally, using the same reverse proxy as in production, and replicating the same network topology are investments that pay off through fewer production incidents. In this respect, the Traefik-based approach to Docker Networking is clearly superior to direct port mapping.
Mironsoft
Docker infrastructure, networking, and development environments for teams
Want Docker Networking set up professionally for your team?
We build a complete Docker networking infrastructure with Traefik, local HTTPS certificates, and automatic service discovery, so your team can develop without port conflicts and without browser warnings.
Traefik setup
A central reverse proxy for all projects with automatic label-based configuration
HTTPS locally
mkcert integration for trustworthy local certificates without browser warnings
Onboarding script
One-click setup for new developers: networks, certificates, and proxy in a single step
10. Summary
Professional Docker Networking for teams solves the classic problems, namely port conflicts, missing HTTPS support, and hard-to-remember URLs, through a clear infrastructure: Traefik as a permanent central reverse proxy with automatic label-based configuration, mkcert for trustworthy HTTPS certificates without browser warnings, dnsmasq for automatic subdomain resolution, and cleanly isolated project networks for security and clarity. Together, these four components make it possible to run any number of projects at the same time.
The most important insight about Docker Networking is that the setup effort is a one-time cost that pays off across every future project. After the initial setup, each new project simply starts with docker compose up: Traefik detects the new service automatically, the certificate already covers every *.localhost domain, and the subdomain name is freely chosen via labels. This saves time on every new project and prevents configuration mistakes caused by copying port numbers between different Compose files.
Docker Networking for Teams: The Essentials at a Glance
Network Isolation
Every project gets its own networks. Databases stay on the internal network only. The shared proxy network is reserved for the reverse proxy.
Traefik as Proxy
Automatic configuration via container labels. No restart needed for new projects. Port 80 and 443 managed centrally.
HTTPS Locally
mkcert creates a local CA plus certificates. Browsers accept them without warnings. One certificate covers every *.localhost domain.
Onboarding
Setup script for new developers: docker network create, mkcert -install, start Traefik. After that, every project just works.