Traefik v1.7 is running within a Docker Swarm, functioning as a global service. Consequently, an instance of Traefik is deployed for each host within our Docker Swarm cluster. It is important to note that the Swarm’s routing mesh is not employed in this setup. Instead, the port mode is configured as “host,” allowing the port to be attached to the host’s network.
traefik:
image: ${REGISTRY}/traefik:1.6
build: ./traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- traefik
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION}
- AWS_HOSTED_ZONE_ID=${AWS_HOSTED_ZONE_ID}
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
mode: host
protocol: tcp
- target: 8080
published: 8080
mode: host
protocol: tcp
deploy:
mode: global
restart_policy:
condition: on-failure
Docker Swarm deployed to AWS and lives behind internal/external load balancers (Classic type).
// terraform SG fragment
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
description = "acme chellange"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
description = "SSL termination"
cidr_blocks = ["0.0.0.0/0"]
}
Let’s assume mydomain.com/mobile-api should be worldwide visible but the rest of app should be available via Whitelist. Hopefully Traefik supports entrypoints by route, so there is nothing easiest then make one more clone of app and set frontend rule targeting to /route.
modile-api:
image: ${REGISTRY}/app:${VERSION:-latest}
networks:
- traefik
deploy:
mode: replicated
replicas: 1
restart_policy:
condition: on-failure
labels:
- traefik.backend=modile-api
- traefik.port=80
- traefik.frontend.rule=Host:${HOST_API};PathPrefix:/mobile-api
- traefik.docker.network=traefik
- traefik.enable=true
app:
image: ${REGISTRY}/app:${VERSION:-latest}
networks:
- traefik
deploy:
mode: replicated
replicas: 1
restart_policy:
condition: on-failure
labels:
- traefik.backend=app
- traefik.port=80
- traefik.frontend.whiteList.sourceRange=${WHITE_LIST}
- traefik.frontend.whiteList.useXForwardedFor=true
- traefik.frontend.rule=Host:${HOST_API}
- traefik.docker.network=traefik
- traefik.enable=true
Important part: set up ProxyProtocol on both side Traefik (reverse-proxy) and AWS ELB. Proxy protocol Traefik side: traefik.toml
[entryPoints.https.whiteList]
sourceRange = ["1.2.3.4/24"] # you can override this part on service level
useXForwardedFor = true
[entryPoints.https.proxyProtocol]
trustedIPs = ["10.0.100.0/24"] # private subnet CIRD block or IPs
[entryPoints.https.forwardedHeaders]
trustedIPs = ["10.0.100.0/24"] # private subnet CIRD block or IPs
Proxy protocol AWS side: (if your listener settings support Proxy Protocol! )
1 # make sure proxyPolicy is disabled. => "BackendServerDescriptions" : []
aws elb describe-load-balancer-policy-types
2 aws elb create-load-balancer-policy --load-balancer-name %lb_name% --policy-name %name% --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=true
3 aws elb set-load-balancer-policies-for-backend-server --load-balancer-name %lb_name% --instance-port 443 --policy-names %policy_name%
4 check (optional)
aws elb describe-load-balancers --load-balancer-name %lb_name%
debug:
aws elb delete-load-balancer-policy --load-balancer-name %lb_name% --policy-name %policy_name%
# get ELB IPs
aws ec2 describe-network-interfaces --filters Name=description,Values="ELB elb_name" --query 'NetworkInterfaces[*].PrivateIpAddresses[*]'
If everything goes as expected you’ll see your IP in X-Forwarded-For header 🎉
Hostname: 6b27211a260c
IP: 127.0.0.1
IP: 10.255.1.59
IP: 172.18.0.13
IP: 10.0.2.65
GET / HTTP/1.1
Host: domain.com
User-Agent: redacted
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,uk-UA;q=0.6,uk;q=0.5
Cache-Control: max-age=0
Connection: keep-alive
Upgrade-Insecure-Requests: 1
X-Forwarded-For: you_real_ip
X-Forwarded-Port: 80
X-Forwarded-Proto: https