Understanding docker compose port wiring for django, react app and haproxy

Viewed 29

I came across a docker-compose.yml which has following port configuration:

    wsgi: 
        ports: 
            - 9090  // ?? Is it by default mapped to host port 80 ??  

    nodejs 
            image: nodejs:myapp 
            ports: 
                - 9999:9999 
            environment: 
                BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/ 

    haproxy 
        ports: 
            - 9854:80        

I am trying to understand how the port wiring is happening here.

nodejs UI app settings needs to specify backend port which is 9854 here. This port is exposed by haproxy setting and is mapped to port 80. I know that wsgi is a django backend app. From its entrypoint.sh (in PS below) and port specification in above docker-compose.yml, I get that django listens to port 9090. But I am unable to get how this port 9090 maps to port 80 (which is then exposed by haproxy at 9854, which in turn is specified in BACKEND_API_URL by nodejs settings).

PS:

Django wsgi app has following in \wsgi\entrypoint.sh:

    nohup gunicorn myapp.wsgi --bind "0.0.0.0:9090" 

And nodejs react app has following in its server.js file:

    const port = process.env.PORT || 9999; 

My whole docker compose file:

version: "3.8"

services:
    postgres:
        image: postgres:11
        volumes:
            - my_app_postgres_volume:/var/lib/postgresql/data
            - type: tmpfs
              target: /dev/shm
              tmpfs:
                size: 536870912 # 512MB
        environment:
            POSTGRES_DB: my_app_db
            POSTGRES_USER: my_app
            POSTGRES_PASSWORD: my_app123
        networks:
            - my_app_network

    redis:
        image: redis:6.2.4
        volumes:
            - my_app_redis_volume:/data
        networks:
            - my_app_network

    wsgi:
        image: wsgi:my_app3_stats
        volumes:
            - /my_app/frontend/static/
            - ./wsgi/my_app:/my_app
            - /my_app/frontend/clientApp/node_modules
            - /etc/timezone:/etc/timezone:ro
            - /etc/localtime:/etc/localtime:ro
        depends_on:
            - postgres
            - redis
        ports:
            - 9090
        environment:
            C_FORCE_ROOT: 'true'
            SERVICE_PORTS: 9090
        networks:
            - my_app_network
        deploy:
            replicas: 1
            update_config:
                parallelism: 1
                delay: 10s
            restart_policy:
                condition: on-failure
                max_attempts: 3
                window: 120s

    nodejs:
        image: nodejs:my_app3_stats
        volumes:
            - ./nodejs/frontend:/frontend
            - /frontend/node_modules
        depends_on:
            - wsgi
        ports:
            - 9999:9999 
        environment:
            BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/ 
        networks:
            - my_app_network

    nginx:
        image: isiq/nginx-brotli:1.21.0
        volumes:
            - ./nginx:/etc/nginx/conf.d:ro
            - ./wsgi/my_app:/my_app:ro
            - my_app_nginx_volume:/var/log/nginx/
            - /etc/timezone:/etc/timezone:ro
            - /etc/localtime:/etc/localtime:ro
        networks:
            - my_app_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:
            - 9854:80
        networks:
            - my_app_network
        deploy:
            placement:
                constraints: [node.role == manager]

volumes:
    my_app_postgres_volume:
    my_app_redis_volume:
    my_app_nginx_volume:

networks:
    my_app_network:
        driver: overlay
1 Answers

On your host, there are three ports visible:

  1. http://aa.bb.cc.dd:9854 forwards to port 80 on the haproxy container.
  2. http://aa.bb.cc.dd:9999 forwards to port 9999 on the nodejs container.
  3. The port shown by docker-compose port wsgi 9090 forwards to port 9090 on the wsgi container.

You don't discuss the HAProxy configuration at all, but it is presumably configured to listen on port 80, and that may be the missing bit of configuration you're looking for.

Between these three containers (so not visible to your front-end application), assuming you don't have any networks: blocks in the Compose file, there are three obvious URLs: http://haproxy:80 (or just http://haproxy), http://nodejs:9999, and http://wsgi:9090 connect to their respective containers. Note that these use the "normal" ports for their service, and not the remapped port for haproxy or the randomly-chosen port for wsgi.

I'm guessing the HAProxy container is configured to do some sort of path-based routing to one or the other of the other containers. If you have this setup, you might be able to configure your React application to not include a host name in the URL at all (BACKEND_API_URL: /api/), which will make it easier to deploy. You do not need the ports: for connections between containers, and if you don't want a caller to be able to reach the back-end services without going via the proxy, you can delete their ports: blocks.

Related