Container Networking Security with Traefik

Table of contents
- Introduction
- Why Traefik and Docker Compose?
- Problem Statement
- Architecture Overview
- Step-by-Step Implementation
- 1. Set Up the Directory Structure
- 2. Generate Certificates for mTLS
- 3. Configure Traefik
- 4. Define Services with Docker Compose
- 5. Start the Infrastructure
- 6. Monitoring with Prometheus and Grafana
- 7. Continuous Logging with ELK Stack
- Architecture Diagram for Monitoring and Logging
- 8. Real-Time Alerting
- 9. Optional Setup - Managing Docker Containers with Portainer
- 10. Testing the Setup
- Conclusion

Introduction
Container networking security is a cornerstone of modern microservices architecture. Tools like Traefik and Docker Compose simplify orchestration and networking, but implementing advanced security features like mutual TLS (mTLS), IP whitelisting, and multi-tenancy often requires precise configurations and a deep understanding of the tools.
In this article, we’ll implement a secure and flexible networking solution using Traefik and Docker Compose, tackling real-world challenges. You’ll learn how to configure encrypted communications, restrict access to specific IP ranges, and isolate environments for multi-tenancy all while maintaining ease of management and scalability.
Why Traefik and Docker Compose?
Traefik is a dynamic, modern reverse proxy and load balancer that integrates seamlessly with Docker and Kubernetes.
Docker Compose simplifies the management of multi-container applications by defining services in a YAML file for orchestration.
Together, they provide a powerful combination for containerized services, automating network routing, and adding security layers.
Problem Statement
Consider an e-commerce platform with multiple microservices: payment, user management, and inventory.
These services need -
mTLS: Secure communication with mutual authentication between services.
IP Whitelisting: Restriction to trusted IPs.
Multi-Tenancy: Logical isolation of tenants for data and network security.
Now let’s implement these using Traefik 2.x and Docker Compose, ensuring a production-ready setup.
Architecture Overview
Components
Traefik as a dynamic reverse proxy and load balancer.
Docker Compose to orchestrate containers.
mTLS for secure, mutual authentication between services.
IP Whitelisting to restrict access based on trusted IP ranges.
Multi-Tenancy for isolated environments with Traefik routers.
High-Level Diagram
graph LR
subgraph "Client Side"
A[Client Requests] --> B[Traefik Reverse Proxy]
end
subgraph "Application Services"
Traefik
B --> C[Service A]
B --> D[Service B]
B --> E[Service C]
end
subgraph "Service Networking"
Security
B --> F[Mutual TLS]
F --> G[Service-to-Service Communication]
B --> H[IP Whitelisting]
H --> I[Access Control]
end
subgraph "Monitoring"
J[Prometheus] --> K[Grafana]
B -->|Metrics| J
end
subgraph "Logging"
L[Logstash] --> M[Elasticsearch]
M --> N[Kibana]
B -->|Logs| L
end
subgraph "Container Management"
Orchestration
O[Portainer] --> B
O --> P[Docker Containers]
B --> Q[Docker Networks]
end
style A stroke:#5c6bc0,stroke-width:2px
style B stroke:#66bb6a,stroke-width:2px
style C stroke:#ffeb3b,stroke-width:2px
style D stroke:#ffeb3b,stroke-width:2px
style E stroke:#ffeb3b,stroke-width:2px
style F stroke:#f44336,stroke-width:2px
style G stroke:#f44336,stroke-width:2px
style H stroke:#2196f3,stroke-width:2px
style I stroke:#2196f3,stroke-width:2px
style J stroke:#9c27b0,stroke-width:2px
style K stroke:#9c27b0,stroke-width:2px
style L stroke:#ff9800,stroke-width:2px
style M stroke:#ff9800,stroke-width:2px
style N stroke:#ff9800,stroke-width:2px
style O stroke:#00bcd4,stroke-width:2px
style P stroke:#00bcd4,stroke-width:2px
style Q stroke:#00bcd4,stroke-width:2px
Explanation
Client Requests are sent to the Traefik Reverse Proxy, which then routes the traffic to various Application Services(Service A, B, C).
Service-to-Service Communication is secured via Mutual TLS, and IP Whitelisting and Access Control are applied for further protection.
Prometheus collects metrics from the services, and Grafana visualizes them for real-time monitoring.
Logging tools (Logstash, Elasticsearch, Kibana) provide a pipeline for gathering, storing, and analyzing logs.
Portainer manages Docker Containers and Docker Networks, facilitating container orchestration and management.
Step-by-Step Implementation
1. Set Up the Directory Structure
/traefik-secure-networking
├── docker-compose.yml # Docker Compose configuration
├── traefik.yml # Traefik static configuration
├── acme.json # Traefik certificate storage
├── certs # Certificates for mTLS
│ ├── ca.crt
│ ├── ca.key
│ ├── server.crt
│ └── server.key
└── services
├── payment
├── user
└── inventory
2. Generate Certificates for mTLS
Run the following commands to generate a root CA and server certificates.
# Generate root CA
openssl genrsa -out certs/ca.key 2048
openssl req -x509 -new -nodes -key certs/ca.key -sha256 -days 365 -out certs/ca.crt -subj "/CN=RootCA"
# Generate server certificate
openssl genrsa -out certs/server.key 2048
openssl req -new -key certs/server.key -out certs/server.csr -subj "/CN=localhost"
openssl x509 -req -in certs/server.csr -CA certs/ca.crt -CAkey certs/ca.key -CAcreateserial -out certs/server.crt -days 365 -sha256
Place the generated files in the certs
directory.
3. Configure Traefik
Create traefik.yml
to define Traefik’s static configuration.
# traefik.yml
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
docker:
exposedByDefault: false # Only expose services explicitly
certificatesResolvers:
default:
acme:
email: "admin@example.com"
storage: "acme.json"
httpChallenge:
entryPoint: web
middlewares:
mtls-auth:
clientAuth:
caFiles:
- "/certs/ca.crt"
optional: false # Enforce mTLS
ip-whitelist:
ipWhiteList:
sourceRange:
- "192.168.1.0/24" # Example: Whitelisted IP range
4. Define Services with Docker Compose
Create docker-compose.yml
with the following content:
version: "3.7"
services:
traefik:
image: traefik:v2.8
container_name: traefik
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.default.acme.email=admin@example.com"
- "--certificatesresolvers.default.acme.storage=acme.json"
- "--certificatesresolvers.default.acme.httpChallenge.entryPoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik.yml:/etc/traefik/traefik.yml"
- "./certs:/certs"
payment:
image: nginx:alpine
container_name: payment
labels:
- "traefik.enable=true"
- "traefik.http.routers.payment.rule=Host(`payment.local`)"
- "traefik.http.routers.payment.entrypoints=websecure"
- "traefik.http.routers.payment.tls=true"
- "traefik.http.routers.payment.tls.certresolver=default"
- "traefik.http.routers.payment.middlewares=mtls-auth@file,ip-whitelist@file"
user:
image: nginx:alpine
container_name: user
labels:
- "traefik.enable=true"
- "traefik.http.routers.user.rule=Host(`user.local`)"
- "traefik.http.routers.user.entrypoints=websecure"
- "traefik.http.routers.user.tls=true"
- "traefik.http.routers.user.tls.certresolver=default"
- "traefik.http.routers.user.middlewares=mtls-auth@file,ip-whitelist@file"
inventory:
image: nginx:alpine
container_name: inventory
labels:
- "traefik.enable=true"
- "traefik.http.routers.inventory.rule=Host(`inventory.local`)"
- "traefik.http.routers.inventory.entrypoints=websecure"
- "traefik.http.routers.inventory.tls=true"
- "traefik.http.routers.inventory.tls.certresolver=default"
- "traefik.http.routers.inventory.middlewares=mtls-auth@file,ip-whitelist@file"
5. Start the Infrastructure
Run the following command to start the containers: docker-compose up -d
6. Monitoring with Prometheus and Grafana
Prometheus is a powerful monitoring tool that scrapes metrics from services, including Traefik, while Grafana visualizes these metrics for easy interpretation.
Steps to Set Up Monitoring
Add Prometheus Metrics in Traefik:
Update the
traefik.yml
configuration file to enable Prometheus:metrics: prometheus: entryPoint: metrics
Expose the
/metrics
endpoint on Traefik:entryPoints: metrics: address: ":8082"
Update your
docker-compose.yml
to expose the metrics entry point:ports: - "8082:8082"
Deploy Prometheus: Add Prometheus to your
docker-compose.yml
:prometheus: image: prom/prometheus container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090"
Create a
prometheus.yml
file to scrape Traefik metrics:scrape_configs: - job_name: "traefik" static_configs: - targets: ["traefik:8082"]
Deploy Grafana: Add Grafana to
docker-compose.yml
:grafana: image: grafana/grafana container_name: grafana ports: - "3000:3000" volumes: - grafana-data:/var/lib/grafana
Access Grafana on
http://localhost:3000
, configure Prometheus as a data source, and import a Traefik dashboard (e.g., Traefik Dashboard JSON.
7. Continuous Logging with ELK Stack
The ELK Stack (Elasticsearch, Logstash, Kibana) is ideal for collecting, analyzing, and visualizing logs from Traefik and Docker containers.
Steps to Set Up Logging
Configure Traefik Logs: Update the
traefik.yml
file to enable access and error logging:log: level: DEBUG filePath: /var/log/traefik/traefik.log accessLog: filePath: /var/log/traefik/access.log
Deploy ELK Stack: Add the ELK stack to
docker-compose.yml
:elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.9.0 container_name: elasticsearch environment: - discovery.type=single-node ports: - "9200:9200" logstash: image: docker.elastic.co/logstash/logstash:8.9.0 container_name: logstash volumes: - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf ports: - "5044:5044" kibana: image: docker.elastic.co/kibana/kibana:8.9.0 container_name: kibana ports: - "5601:5601"
Configure Logstash: Create a
logstash.conf
file to ingest logs:input { file { path => "/var/log/traefik/*.log" start_position => "beginning" } } output { elasticsearch { hosts => ["http://elasticsearch:9200"] index => "traefik-logs" } }
Visualize in Kibana: Access Kibana on
http://localhost:5601
:Create an index pattern for
traefik-logs
.Build visualizations and dashboards to monitor Traefik logs.
Architecture Diagram for Monitoring and Logging
graph TD
A[Client Requests] --> B[Traefik Proxy]
B --> C[Application Services]
subgraph Monitoring
D[Prometheus] --> E[Grafana]
B -->|Metrics| D
end
subgraph Logging
B -->|Logs| F[Logstash]
F --> G[Elasticsearch]
G --> H[Kibana]
end
subgraph Container Management
I[Portainer] --> B
I --> J[Docker Containers]
end
D -->|Alerts| I[Alertmanager]
Benefits -
Improved Observability: Real-time metrics and logs provide a clear picture of the system’s health and performance.
Proactive Security: Alerts help detect anomalies like unauthorized access or high request latencies, enabling faster incident response.
Simplified Debugging: Detailed logs in ELK and visual dashboards in Grafana aid in root cause analysis.
Compliance: Logs ensure auditable trails for compliance requirements.
8. Real-Time Alerting
Integrate Alertmanager with Prometheus to set up real-time alerts:
Define alert rules in
prometheus.yml
:alerting: alertmanagers: - static_configs: - targets: ["alertmanager:9093"] rule_files: - "alert_rules.yml"
Create
alert_rules.yml
to define alerts:groups: - name: traefik_alerts rules: - alert: HighRequestLatency expr: traefik_backend_request_duration_seconds_sum > 1 for: 2m labels: severity: warning annotations: summary: "High request latency detected"
Deploy Alertmanager with Docker Compose:
alertmanager: image: prom/alertmanager container_name: alertmanager ports: - "9093:9093"
9. Optional Setup - Managing Docker Containers with Portainer
Portainer is a powerful and user-friendly management tool for Docker environments. It provides a web-based UI for managing Docker containers, images, networks, volumes, and other Docker resources. Integrating Portainer into your architecture allows you to easily monitor, manage, and control your containers, helping developers and administrators work more efficiently.
Steps to Set Up Portainer
1. Add Portainer to Docker Compose
Update
docker-compose.yml
: In yourdocker-compose.yml
file, add a section for Portainer. This will deploy Portainer as a Docker container with access to the Docker socket for container management.version: '3' services: # Existing services (Traefik, Prometheus, Logstash, etc.) ... # Portainer Service portainer: image: portainer/portainer-ce container_name: portainer restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data ports: - "9000:9000" # Port for the Portainer web interface networks: - traefik volumes: portainer_data:
Network Configuration: Ensure that Portainer is connected to the same network as your other services. In this example, it's connected to the
traefik
network. This allows Portainer to interact with Docker services managed by Traefik.
2. Access Portainer Dashboard
Once Portainer is running, you can access it through a web browser by navigating to
http://localhost:9000
.The first time you access Portainer, you will need to create an admin account for secure access.
3. Managing Docker Containers via Portainer
Container Overview: The Portainer dashboard allows you to see all your running containers, including Traefik, Prometheus, Grafana, and other Docker containers.
Container Operations:
Start/Stop/Restart: You can manage container lifecycles directly from the dashboard.
Logs: View logs for each container to debug issues or monitor performance in real-time.
Stats: Monitor resource usage (CPU, memory, network) for each container.
Terminal Access: Portainer allows you to access the container's terminal directly, making it easy to execute commands inside containers.
Deploy New Containers: You can deploy new containers using the web interface by specifying container images, environment variables, volumes, and other configurations.
4. Additional Features of Portainer
Access Control: Portainer supports role-based access control (RBAC), allowing you to restrict permissions for different users based on roles. This is useful in multi-tenant environments.
Multi-Docker Environment: Portainer can manage multiple Docker environments and Swarm clusters, making it ideal for managing large-scale deployments.
Docker Swarm: If you're running a Docker Swarm cluster, Portainer can manage and visualize swarm services, stacks, and nodes.
5. Secure Portainer Access (Optional)
To ensure Portainer’s web interface is secure, especially when exposed in a production environment, you should consider using HTTPS and authentication mechanisms.
Enable HTTPS via Traefik:
Update Traefik to reverse proxy the Portainer web interface and secure it with a certificate:
labels: - "traefik.enable=true" - "traefik.http.routers.portainer.rule=Host(`portainer.yourdomain.com`)" - "traefik.http.routers.portainer.entrypoints=https" - "traefik.http.routers.portainer.tls=true" - "traefik.http.routers.portainer.tls.certresolver=myresolver"
This configuration assumes you have already set up Traefik’s ACME (Let’s Encrypt) integration for automatic HTTPS certificate generation.
Portainer Authentication: Enable the authentication feature in Portainer for secure access. After creating an admin account, set up additional users and assign them appropriate roles for limited access.
Benefits -
User-Friendly UI: Portainer provides an intuitive web interface, making it easier to manage Docker containers without relying solely on the command line.
Centralized Control: For teams managing multiple services, Portainer consolidates container management tasks into one platform, improving workflow efficiency.
Secure Access: Portainer's role-based access control and secure authentication prevent unauthorized users from accessing your containerized applications.
Cross-Platform Support: Whether you're using Docker Swarm or standalone Docker, Portainer works across various Docker environments.
10. Testing the Setup
Test mTLS: Use cURL to access the services with client certificates:
curl --cert certs/server.crt --key certs/server.key --cacert certs/ca.crt https://payment.local
Test IP Whitelisting: Attempt access from allowed and disallowed IP ranges.
Multi-Tenancy: Test routing by accessing
https://payment.local
,https://user.local
, andhttps://inventory.local
.
Conclusion
Integrating Traefik with advanced networking security setups like mutual TLS, IP whitelisting, and multi-tenancycreates a robust and scalable containerized architecture. Coupling this with powerful monitoring and logging tools like Prometheus, Grafana, and the ELK stack ensures that you can maintain observability and security at scale. Adding Portainer as an optional container management layer simplifies the administration of your Docker containers, providing a user-friendly interface for operational tasks.
This implementation not only improves security but also streamlines container management and enhances the overall efficiency of your DevOps processes. By setting up these advanced configurations, you ensure that your microservices environment is secure, isolated, and resilient to attacks, all while leveraging the dynamic capabilities of Traefik and the flexibility of Docker Compose.
Subscribe to my newsletter
Read articles from Subhanshu Mohan Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Subhanshu Mohan Gupta
Subhanshu Mohan Gupta
A passionate AI DevOps Engineer specialized in creating secure, scalable, and efficient systems that bridge development and operations. My expertise lies in automating complex processes, integrating AI-driven solutions, and ensuring seamless, secure delivery pipelines. With a deep understanding of cloud infrastructure, CI/CD, and cybersecurity, I thrive on solving challenges at the intersection of innovation and security, driving continuous improvement in both technology and team dynamics.