2

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: [email protected]
            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: [email protected]
            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?

1 Answer 1

0

Although you've set the network_mode to host, I believe you need to set the ports -> mode to host to get the real client IP.

For example:

ports: 
  - mode: host 

Hopefully this works for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.