Hi, I’m trying to get the visitor’s IP addresses in my PHP webapp (and its logs). This is my setup:
Virtual Private Server running Debian 12, hosted in a data center, reachable via SSH
Docker 28.0.4 installed and running smoothly
Traefik:latest (v3) container is bound to ports 80 and 443 of the host
Several containers with PHP webapps, all on individual (sub-)domains, secured through Let’s Encrypt certificates
All services are reachable and work as expected. Some have their private database container.
I use docker compose to manage my collection of containers
In the logs of all containers, I see Docker’s gateway IP-address (172.x.x.x) as source of a request. The X-Forwarded-For and X-Real-IP HTTP-headers are present, but contain 172.x.x.x, too. It is only in Traefik’s logs that I occasionally see a public IP-address.
Question 1: How can I debug where the public IP gets dropped, and the gateway’s address pops in its place?
Question 2: What is the simplest docker-compose setup for my situation?
I have seen so many forum- and blog posts about this issue, I don’t know what to do next.
Lets assume the Traefik container uses network_mode: host to have raw access to the host’s network interfaces, then Treafik is able to see the source ip of coming requests. A major drawback is that a container using network_mode can not be part of any container network. This is suboptimal for a reverse proxy container.
Though, if you would initiate the swarm mode on your host, and deploy your compose file as swarm stack, you could leverage mode: host in the long syntax in the port mapping section of the service to retain the source ip without needing network_mode: host (which wouldn’t work with swarm anyway).
Thanks for this quick reply. Would you care to elaborate on the swarm mode?
This is a simplified example of my setup (Traefik and a whoami-container). The network named proxy, I created by issuing docker network create proxy. At the moment, it’s a bridge-network that connects all the webapp-containers and Traefik.
The swarm mode is enabled for the Docker Engine, not for a compose file. You will need to change the ports part to the long syntax,as I shared in my previous post.