I have a following docker compose file:
version: "3.8"
services:
postgres:
image: postgres:11
volumes:
- myapp_postgres_volume:/var/lib/postgresql/data
- type: tmpfs
target: /dev/shm
tmpfs:
size: 536870912 # 512MB
environment:
POSTGRES_DB: elearning_academy
POSTGRES_USER: myapp
POSTGRES_PASSWORD: myapp123
networks:
- myapp_network
pgadmin:
image: dpage/pgadmin4:5.4
volumes:
- myapp_pgadmin_volume:/var/lib/pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: myapp@cse.iitb.ac.in
PGADMIN_DEFAULT_PASSWORD: myapp123
ports:
- 8080:80
networks:
- myapp_network
redis:
image: redis:6.2.4
volumes:
- myapp_redis_volume:/data
networks:
- myapp_network
wsgi:
image: wsgi:myapp3
volumes:
- /myapp/frontend/static/
- ./wsgi/myapp:/myapp
- /myapp/frontend/clientApp/node_modules
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- postgres
- redis
ports:
- 9090
- 3000:3000
- 8000:8000
environment:
C_FORCE_ROOT: 'true'
SERVICE_PORTS: 9090
networks:
- myapp_network
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
nodejs:
image: nodejs:myapp3
volumes:
- ./nodejs/frontend:/frontend
- /frontend/node_modules
depends_on:
- wsgi
ports:
- 9000:9000 # development
- 9999:9999 # production
environment:
BACKEND_API_URL: http://0.0.0.0:3000
networks:
- myapp_network
nginx:
image: mydockeraccount/nginx-brotli:1.21.0
volumes:
- ./nginx:/etc/nginx/conf.d:ro
- ./wsgi/myapp:/myapp:ro
- myapp_nginx_volume:/var/log/nginx/
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- myapp_network
haproxy:
image: haproxy:2.3.9
volumes:
- ./haproxy:/usr/local/etc/haproxy/:ro
- /var/run/docker.sock:/var/run/docker.sock
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- wsgi
- nodejs
- nginx
ports:
- 9763:80
networks:
- myapp_network
deploy:
placement:
constraints: [node.role == manager]
volumes:
myapp_postgres_volume:
myapp_redis_volume:
myapp_nginx_volume:
myapp_pgadmin_volume:
networks:
myapp_network:
driver: overlay
As you can see I have a nodejs app and a django (wsgi) app. I have written django middleware to log incoming IP to the database. However, it logs the IP different from the actual IP. After reading online, I came to know that this might be due to how the docker network is configured (overlay as can be seen in last line of above docker compose file). I read online that I need to configure docker network in host mode. So I tried adding network_mode: host to each service and removing networks section from above file.
version: "3.8"
services:
postgres:
image: postgres:11
volumes:
- myapp_postgres_volume:/var/lib/postgresql/data
- type: tmpfs
target: /dev/shm
tmpfs:
size: 536870912 # 512MB
environment:
POSTGRES_DB: elearning_academy
POSTGRES_USER: myapp
POSTGRES_PASSWORD: myapp123
network_mode: host
pgadmin:
image: dpage/pgadmin4:5.4
volumes:
- myapp_pgadmin_volume:/var/lib/pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: myapp@cse.iitb.ac.in
PGADMIN_DEFAULT_PASSWORD: myapp123
ports:
- 8080:80
network_mode: host
redis:
image: redis:6.2.4
volumes:
- myapp_redis_volume:/data
network_mode: host
wsgi:
image: wsgi:myapp3
volumes:
- /myapp/frontend/static/
- ./wsgi/myapp:/myapp
- /myapp/frontend/clientApp/node_modules
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- postgres
- redis
ports:
- 9090
- 3000:3000
- 8000:8000
environment:
C_FORCE_ROOT: 'true'
SERVICE_PORTS: 9090
network_mode: host
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
nodejs:
image: nodejs:myapp3
volumes:
- ./nodejs/frontend:/frontend
- /frontend/node_modules
depends_on:
- wsgi
ports:
- 9000:9000 # development
- 9999:9999 # production
environment:
BACKEND_API_URL: http://0.0.0.0:3000
network_mode: host
nginx:
image: mydockeraccount/nginx-brotli:1.21.0
volumes:
- ./nginx:/etc/nginx/conf.d:ro
- ./wsgi/myapp:/myapp:ro
- myapp_nginx_volume:/var/log/nginx/
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
network_mode: host
haproxy:
image: haproxy:2.3.9
volumes:
- ./haproxy:/usr/local/etc/haproxy/:ro
- /var/run/docker.sock:/var/run/docker.sock
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- wsgi
- nodejs
- nginx
ports:
- 9763:80
network_mode: host
deploy:
placement:
constraints: [node.role == manager]
volumes:
myapp_postgres_volume:
myapp_redis_volume:
myapp_nginx_volume:
myapp_pgadmin_volume:
When I run docker stack deploy -c docker-compose.yml my_stack, it outputs Ignoring unsupported options: network_mode. I tried to check how the network is created:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
tp6olv2atq06 myapp_default overlay swarm
So it ended up being configured in the overlay mode only and not in host mode.
Further reading online revealed that host network mode is not available for swarm started with docker stack deploy. (Possible related open issue: github link).
For development, I simply connect vscode to nodejs and wsgi containers and run the apps in debug mode. So nginx is not involved at during development. However, in the deployment we do use nginx, which is also deployed as a docker container.
Now I have following questions:
Q1. Is configuring nginx to set X-Real-IP header with actual IP only solution?
Q2. Cant I do some docker config or changes in docker compose file to obtain real IP address inside docker container (django in my case), without doing any changes to nginx? Say somehow configuring those containers to be on host network?
Q3. If somehow I configure nginx to set X-Real-IP header, will it work even while development, given that nginx is not involved while development?
Q4. The comments to this answer seem to suggest that if the nginx itself is running as a docker container, then configuring it to add X-Real-IP header will not work. Is it so?