The issue is that the default behavior of Docker Swarm is to use an overlay network, which hides the client's IP address. To get the real IP address of the client, you need to use the mode: host option in the ports section of the docker-compose.yml file. However, this causes the issue of only one replica working. To solve this, you can use a reverse proxy like Traefik or HAProxy to distribute the traffic to multiple replicas. Here's an example docker-compose.yml file using Traefik:
version: '3.9'
services:
nginx:
image: nginx
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.rule=Host(`example.com`)"
- "traefik.http.services.nginx.loadbalancer.server.port=80"
networks:
- traefik
networks:
traefik:
external: true
This configuration sets up a single Nginx service with Traefik as the reverse proxy. The traefik.enable=true label tells Traefik to use this service. The traefik.http.routers.nginx.rule=Host('example.com') label tells Traefik to route traffic for example.com to this service. The traefik.http.services.nginx.loadbalancer.server.port=80 label tells Traefik to use port 80 for load balancing. Finally, the networks section sets up the traefik network as an external network, which allows Traefik to access the Nginx service.