docker-compose.yml file and attach both the Traefik container and your application containers to it. By exposing port 80 and 443 from the Traefik service and utilizing dynamic configuration files or labels, you can route incoming HTTPS traffic securely to your internal web applications without exposing their internal ports directly to the host machine.
Prerequisites and Network Definition
Before deploying any services, ensure that Docker and Docker Compose are installed on your host system. The core of this setup relies on creating a shared network that allows Traefik to communicate with your backend containers. You should create a dedicated network, often namedweb or traefik_proxy, which serves as the bridge between the external world and your internal services.
In your docker-compose.yml file, start by defining the networks section at the root level. This ensures that all services referencing this network name will be connected to the same virtual switch within the Docker daemon. For example:
networks:
web:
driver: bridge
This network definition is critical because Traefik needs to resolve the DNS names of your other containers. If your application containers are not on the same network as Traefik, the proxy will fail to forward requests, resulting in connection refused errors. Ensure that every service that needs to be proxied explicitly lists this network in its configuration.
Configuring the Traefik Container
The Traefik container acts as the entry point for all HTTP and HTTPS traffic. It requires specific volumes to read its configuration and access the Docker socket to discover other services dynamically. You must mount the Docker socket (/var/run/docker.sock) so Traefik can listen for events like container starts and stops. Additionally, mount a directory containing your static and dynamic configuration files.
Your docker-compose.yml for the Traefik service should look similar to this:
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
- ./config/dynamic/:/etc/traefik/dynamic/:ro
networks:
- web
Notice that we expose ports 80 and 443. Port 80 is typically used for HTTP-to-HTTPS redirection, while 443 handles the actual encrypted traffic. The ro flag on the volumes ensures that Traefik cannot accidentally modify the host's Docker socket or config files, enhancing security. This setup aligns with best practices for exposing Docker containers to external networks, as discussed in our guide on Exposing Docker Container to External Networks on Ubuntu 22.04.3 LTS.
Static Configuration File
Create atraefik.yml file in your ./config directory. This file defines the global settings, such as the entry points and the providers Traefik should use. Since we are using Docker, we enable the Docker provider and tell Traefik to automatically search for labels on containers.
global:
checkNewVersion: true
sendAnonymousUsage: false
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: web
api:
dashboard: true
Setting exposedByDefault: false is crucial. It means Traefik will only route traffic to containers that explicitly request it via labels. This prevents accidental exposure of internal tools or health-check endpoints. The network: web line tells the Docker provider to only look at containers attached to the web network we defined earlier.
Labeling Application Containers
Your web applications (e.g., WordPress, Nextcloud, or custom apps) do not need complex configurations if they are correctly labeled. In their respectivedocker-compose.yml files or service definitions, add the following labels to expose them through Traefik.
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`support.example.com`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls=true"
- "traefik.http.services.myapp.loadbalancer.server.port=80"
These labels instruct Traefik to enable routing for this container, match the domain support.example.com, use the secure entry point, enable TLS, and forward traffic to port 80 inside the container. This method eliminates the need for manual Nginx or Apache configuration files for each app, streamlining deployment. If you encounter issues with context ignoring, refer to our troubleshooting guide for Nginx-proxy Ignoring Server Context, as the logic for rule matching is conceptually similar.
TLS Certificate Management
For production environments, you should automate SSL certificate renewal using Let's Encrypt. Add a certificatesResolvers section to yourtraefik.yml:
certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
storage: acme.json
httpChallenge:
entryPoint: web
Then, update your router label to include the resolver: - "traefik.http.routers.myapp.tls.certresolver=letsencrypt". Ensure that port 80 is accessible from the internet for the ACME challenge to validate domain ownership. The acme.json file must have restricted permissions (chmod 600) to protect your private keys.
Frequently Asked Questions
Why is my container not reachable via Traefik?
Most commonly, the container is not attached to the same Docker network as the Traefik service. Check your docker-compose.yml to ensure both services list the same network under the networks key. Also verify that traefik.enable=true is present in the target container's labels.
How do I handle multiple domains on the same server?
You can define separate routers for each domain using different Host() rules in the labels. Each router can point to a different service and use the same TLS resolver. This allows you to host multiple distinct applications under one Traefik instance efficiently.
Can I use Traefik with non-Docker services?
Yes, Traefik supports Kubernetes, Consul, and file-based configurations. However, for containerized environments, the Docker provider is the most seamless. If you are running mixed workloads, you might need to combine providers, though this adds complexity to your configuration.
What happens if the ACME challenge fails?
If the HTTP challenge fails, Traefik will not obtain or renew the certificate. Ensure that port 80 is open on your firewall and that your DNS records correctly point to your server's IP. Check the Traefik logs for specific error messages related to validation timeouts or permission denied errors.
Is it safe to expose the Traefik dashboard?
The dashboard provides visibility into your routing but should never be exposed publicly without authentication. Secure it by adding basic auth middleware or restricting access to internal IPs only. Never expose the API endpoint to the public internet to prevent unauthorized configuration changes.