I’m using Traefik v2.2 as a reverse proxy for my docker containers. Basically all HTTP or HTTPS traffic is handled by Traefik as an ingress container and then routing according to rules defined in my docker-compose file to the appropriate internal container.
Something that I’ve needed to do for a project is add a header to an inbound request in order to identify that the request has been processed by traefik. I tried to follow the documentation but found it… lacking. For anyone interested in the official documentation for adding headers to Traefik you can find it here: https://docs.traefik.io/middlewares/headers/
What I’ve ended up with is a service container (nginx in my case) that looks like this:
nginx: image: nginx:stable-alpine volumes: - ./src:/var/www - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf labels: - "traefik.enable=true" - "traefik.http.routers.router1.rule=Host(`localhost`)" - "traefik.http.middlewares.testHeader.headers.customrequestheaders.test-header=new-header" - "traefik.http.routers.router1.middlewares=testHeader" php: image: php:7.4-fpm volumes: - ./src:/var/www
Now something that threw me was the header “test_header” doesn’t exist in requests handled by nginx. A linked PHP container simply running print_r($_SERVER)
dumps all the variables to the page. It’s only at this point I discovered that Traefik adds HTTP_
to the header. So instead of :
test-header = new-header
you get:
HTTP_TEST_HEADER = new-header
I think this is one of those things that you can waste alot of time on if you don’t know that Traefik is re-writing the header values in this way.
Looking back at the Traefik configuration, to add a header you basically have two steps:
First, create a new header. This is done in the following format:
traefik.http.middlewares.{your header group name}.headers.customrequestheaders.{header key}={header value}
As an example:
- "traefik.http.middlewares.testHeader.headers.customrequestheaders.test-header=new-header"
This creates a header `HTTP_TEST_HEADER` and assigns it to the `testHeader` middleware group.
Secondly, assign this middleware group to the router you’re using for your service. In my case that’s an nginx container on a router `router1`. This takes the following format:
traefik.http.routers.{router name}.middlewares={middleware name}
As an example:
- "traefik.http.routers.router1.middlewares=testHeader"
If you’re not sure what this looks like in the context of the other containers check the first, more complete example or see the entire docker-compose file below (NOTE: this file exposes the Traefik API for debugging purposes, so don’t blindly deploy it to production):
version: '3' services: proxy: image: traefik:v2.2 command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--api.insecure=true" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" nginx: image: nginx:stable-alpine volumes: - ./src:/var/www - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf labels: - "traefik.enable=true" - "traefik.http.routers.router1.rule=Host(`localhost`)" - "traefik.http.middlewares.testHeader.headers.customrequestheaders.test-header=new-header" - "traefik.http.routers.router1.middlewares=testHeader" - "traefik.http.middlewares.test-ratelimit.ratelimit.average=1" - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" php: image: php:7.4-fpm volumes: - ./src:/var/www