解析Django、React应用与HAProxy的Docker Compose端口映射逻辑
核心疑问
我拿到一份docker-compose.yml配置,其中端口配置片段如下:
wsgi: ports: - 9090 // ?? 是否默认映射到主机80端口 ?? nodejs: image: nodejs:myapp ports: - 9999:9999 environment: BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/ haproxy: ports: - 9854:80
我想搞懂其中的端口连接逻辑:Node.js前端配置的后端API端口是9854,这个端口由HAProxy暴露并映射到容器内的80端口;已知WSGI是Django后端应用,从entrypoint.sh和docker-compose配置能看到Django监听9090端口,但不清楚9090端口如何和HAProxy的80端口关联,进而被Node.js的BACKEND_API_URL引用。
补充信息
Django WSGI应用的entrypoint.sh
nohup gunicorn myapp.wsgi --bind "0.0.0.0:9090"
Node.js React应用的server.js
const port = process.env.PORT || 9999;
完整docker-compose.yml配置
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. WSGI的9090端口映射规则
docker-compose中ports: - 9090的写法,是将容器内的9090端口随机映射到主机的一个未被占用的端口,并非默认映射主机80端口。不过这个映射对内部服务通信无意义——所有服务都在my_app_network自定义网络中,容器之间可直接通过服务名+容器内端口通信,不需要走主机端口映射。
2. WSGI与HAProxy的关联关键
HAProxy的配置文件(挂载路径./haproxy:/usr/local/etc/haproxy/:ro)里配置了反向代理规则,把HAProxy容器内80端口的请求转发到WSGI服务的9090端口。在同一Docker网络中,HAProxy可直接用服务名wsgi访问WSGI容器,示例规则如下:
frontend http_front bind *:80 default_backend http_back backend http_back server wsgi_server wsgi:9090 check
这就是9090与HAProxy 80端口关联的核心——HAProxy作为反向代理,将自身80端口的请求转发给WSGI的9090端口。
3. Node.js的BACKEND_API_URL调用链路
Node.js前端配置的BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/中,aa.bb.cc.dd是主机IP,9854是主机映射到HAProxy容器80端口的端口。完整请求链路:
Node.js前端 → 主机9854端口 → HAProxy容器80端口 → HAProxy转发到WSGI服务的9090端口 → Django后端处理请求
额外说明
- WSGI的
ports: -9090映射到主机的端口,主要用于开发时直接访问后端调试,生产环境一般不需要该映射,因为外部请求均通过HAProxy统一入口。 - HAProxy挂载了
/var/run/docker.sock,可能使用了容器自动发现配置(如docker-gen),自动将WSGI、Node.js、Nginx等服务加入代理规则,无需手动编写后端服务器地址。
内容的提问来源于stack exchange,提问作者Rnj

