NGINX反向代理多容器服务8080端口占用问题排查
问题根因
- 核心问题是你给
se-kpi-sim(Django后端)、se-kpi-sim-ui(Vue前端)、reverse-proxy(Nginx反向代理)三个容器全部配置了network_mode: "host",该模式下所有容器共享宿主机网络命名空间,端口直接绑定宿主机,完全失去Docker网络隔离能力,多个服务抢占同个端口就会触发地址占用报错。 - 你看到的
bind() to 0.0.0.0:8080 failed报错,是Vue UI容器内部服务默认监听8080端口,启动时发现宿主机8080端口已经被其他进程(异常退出残留的容器进程、宿主机其他服务)占用导致的。 - 现有反向代理配置里的
proxy_pass写http://0.0.0.0:端口是错误写法,0.0.0.0是服务绑定监听的地址,不是内网访问的目标地址,就算使用host网络,访问本机服务也应该用127.0.0.1,更合理的方案是放弃host网络,用Docker默认桥接网络走服务名互访。
修复步骤
调整docker-compose配置
移除三个业务/代理容器的network_mode: "host"配置,所有服务加入同一个默认内网,仅给反向代理暴露对外的80端口即可,调整后配置如下:
version: '3.2' services: se-kpi-sim: image: test-app:0.0.1 restart: unless-stopped environment: MODEL_NAME: "model_final.pickle.dat" # 仅Docker内网可访问,不对外暴露端口 expose: - "5000" se-kpi-sim-ui: image: test-ui:0.0.3 restart: unless-stopped # 仅Docker内网可访问,不对外暴露端口 expose: - "3000" reverse-proxy: image: test-proxy:0.0.7 restart: unless-stopped # 仅反向代理对外暴露80端口 ports: - "80:80" depends_on: - se-kpi-sim - se-kpi-sim-ui database: image: postgres environment: POSTGRES_PASSWORD: password POSTGRES_USER: kpi_sim_user POSTGRES_DB: kpi_sim POSTGRES_HOST_AUTH_METHOD: trust # 非调试场景不需要映射数据库端口到宿主机,避免安全风险 expose: - "5432" volumes: - database:/var/lib/postgresql/data restart: unless-stopped volumes: database:
切换到桥接网络后,每个容器有独立的网络栈,UI容器内部监听的8080端口不会和宿主机或其他容器的端口冲突,之前的8080端口占用报错会直接消失。
修正Nginx反向代理配置
把proxy_pass的目标地址从0.0.0.0改成docker-compose对应的服务名,Docker内置DNS会自动把服务名解析到对应容器的内网IP,不需要手动写死IP,补充通用请求头配置方便后端获取真实用户IP,修正后配置如下:
server { listen 80; listen [::]:80; location / { proxy_pass http://se-kpi-sim-ui:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /predict { proxy_pass http://se-kpi-sim:5000/predict; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /aggregate { proxy_pass http://se-kpi-sim:5000/aggregate; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /media/pictures { proxy_pass http://se-kpi-sim:5000/media/pictures; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } access_log /opt/bitnami/nginx/logs/anomaly_access.log; error_log /opt/bitnami/nginx/logs/anomaly_error.log; }
清理残留进程后重启服务
在部署目录执行以下命令,清理旧的残留容器、确认端口无占用后重启服务:
# 停止并删除所有旧容器 docker compose down # 检查关键端口是否被残留进程占用 ss -tulpn | grep -E ':(80|3000|5000|8080)\s' # 如果有残留进程占用,执行kill -9 对应PID 释放端口 # 后台启动所有服务 docker compose up -d
后续配置说明
- 当前部署模式下只有反向代理的80端口对外暴露,前端、后端、数据库端口都仅在Docker内网可访问,既避免端口冲突,也能降低服务被攻击的风险。
- 后续调试完成要开放443端口支持HTTPS时,只需要给reverse-proxy服务增加
443:443的端口映射,在Nginx配置里新增443端口监听和证书配置即可,不需要调整其他业务服务。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

