You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中Nginx代理Mongo Express资源404问题求助

Docker多容器环境下Nginx代理mongo-express静态资源404问题

我搭建了包含web、api、mongodb、mongo-express和nginx的Docker多容器环境,目标是用Nginx实现流量转发。目前访问localhost/api和web服务均正常,但访问localhost/mongo-express时页面加载成功,但其请求的静态资源全部返回404错误。我是Docker新手,完全不熟悉Nginx。

当前的docker-compose配置:

version: '3'
services:
  # Web App Container
  web:
    build:
      context: web
    container_name: web
    networks:
      - mynetwork

  # API Container
  api:
    build:
      context: api
    container_name: api
    networks:
      - mynetwork

  # Nginx Container
  nginx:
    image: nginx:1.21-alpine
    container_name: nginx
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - "80:80"
      - "403:403"
    depends_on:
      - web
      - api
      - mongodb
      - mongo-express
    networks:
      - mynetwork

  # Mongodb Container
  mongodb:
    image: mongo
    container_name: mongodb
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
    volumes:
      - mongodb_data:/data/db
    networks:
      - mynetwork

  # Mongo Express Container
  mongo-express:
    image: mongo-express
    container_name: mongo-express
    restart: always
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: admin
      ME_CONFIG_MONGODB_ADMINPASSWORD: admin
      ME_CONFIG_MONGODB_URL: mongodb://root:root@mongodb:27017/
    depends_on:
      - mongodb
    networks:
      - mynetwork

volumes:
  mongodb_data:

networks:
  mynetwork:

Nginx配置文件:

# nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '
                      '$status $body_bytes_sent \"$http_referer\" '
                      '\"$http_user_agent\" \"$http_x_forwarded_for\"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    server {
        listen 80;
        server_name example.com www.example.com;

        location / {
            proxy_pass http://web:8080/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        location /api/ {
            rewrite ^/api(/.*)$ $1 break;
            proxy_pass http://api:3000/;
            # Additional proxy settings for the API if needed
        }

        location /mongo-express/ {
            rewrite ^/mongo-express(/.*)$ $1 break;
            proxy_pass http://mongo-express:8081/;
            # Additional proxy settings for Mongo Express if needed
        }

        location /mongodb/ {
            rewrite ^/mongodb(/.*)$ $1 break;
            proxy_pass http://mongodb:27017/;
            # Additional proxy settings for MongoDB if needed
        }

        error_page 404 /404.html/;
        location = /40x.html/ {
        }

        error_page 500 502 503 504 /50x.html/;
        location = /50x.html/ {
        }
    }
}

我原本认为反向代理能正常解析这些资源,尝试过调整Nginx配置、在docker-compose中设置ME_CONFIG_SITE_BASEURL: mongo-express,但均无效。我不仅需要解决方案,还希望理解问题产生的原因。


问题原因

  1. 静态资源路径不匹配:mongo-express返回的页面中,静态资源(CSS、JS、图片等)使用绝对路径(比如/css/main.css)。当通过localhost/mongo-express访问时,浏览器会直接请求localhost/css/main.css,这个路径会被Nginx匹配到根路径的web服务,无法找到资源,返回404。
  2. baseurl配置与转发逻辑冲突:你尝试设置ME_CONFIG_SITE_BASEURL: mongo-express,但Nginx的rewrite规则把请求前缀/mongo-express/去掉后转发给容器,导致容器生成的带前缀的资源路径(比如/mongo-express/css/main.css)被截断,无法匹配转发规则。

解决方案

提供两种可行方案,任选其一即可:

方案一:同步baseurl与Nginx转发路径(推荐)

让mongo-express生成的资源路径自带代理前缀,和Nginx转发规则完全匹配。

  1. 修改docker-compose的mongo-express配置:
    添加ME_CONFIG_SITE_BASEURL环境变量,注意值要以斜杠结尾:
    mongo-express:
      image: mongo-express
      container_name: mongo-express
      restart: always
      environment:
        ME_CONFIG_MONGODB_ADMINUSERNAME: admin
        ME_CONFIG_MONGODB_ADMINPASSWORD: admin
        ME_CONFIG_MONGODB_URL: mongodb://root:root@mongodb:27017/
        ME_CONFIG_SITE_BASEURL: /mongo-express/  # 必须带结尾斜杠
      depends_on:
        - mongodb
      networks:
        - mynetwork
    
  2. 修改Nginx的location配置:
    去掉rewrite规则,让Nginx完整转发前缀路径到容器:
    location /mongo-express/ {
        proxy_pass http://mongo-express:8081/mongo-express/;  # 和baseurl保持一致
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    

原理:ME_CONFIG_SITE_BASEURL会让mongo-express生成的所有资源路径都带上/mongo-express/前缀,浏览器请求时发送localhost/mongo-express/css/main.css,Nginx直接转发到容器内对应路径,资源即可正常加载。

方案二:用Nginx替换页面中的资源路径

如果不想修改mongo-express的配置,可以用Nginx的sub_filter模块,把页面里的绝对路径替换成带代理前缀的路径:
修改Nginx的location配置:

location /mongo-express/ {
    rewrite ^/mongo-express(/.*)$ $1 break;
    proxy_pass http://mongo-express:8081/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    # 替换页面中所有绝对路径的前缀
    sub_filter 'href="/' 'href="/mongo-express/';
    sub_filter 'src="/' 'src="/mongo-express/';
    sub_filter_once off;  # 确保替换所有匹配项
}

原理:Nginx先去掉前缀转发请求给mongo-express,再把返回页面里的href="/和src="/替换成href="/mongo-express/,浏览器会请求带前缀的资源路径,被当前location匹配并转发给容器。


内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:15:54