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

Docker环境下Nginx反向代理子目录至Apache容器失效求助

我来帮你排查这个反向代理的问题!既然你已经确认所有Apache容器本身能正常运行,那问题大概率出在Nginx的location配置细节,或者Apache应用对代理路径的适配处理上,下面给你一步步拆解解决方案:

1. 先搞定Nginx的核心配置坑:proxy_pass的斜杠问题

这是子目录反向代理最容易踩的雷!proxy_pass末尾的斜杠决定了Nginx如何传递URI给后端Apache,直接影响路径匹配:

错误示例(导致404的常见原因)

如果你的配置是这样:

location /parts {
    proxy_pass http://apache-parts;
}

当用户请求/parts/foo时,Nginx会把完整的/parts/foo传给Apache,而你的Apache应用是部署在根路径(/)下的,自然找不到/parts/foo这个资源。

正确配置二选一

方式一:带尾斜杠的location + proxy_pass
location /parts/ {
    proxy_pass http://apache-parts/;
    # 必须添加的代理头,保证后端能正确识别请求来源
    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 /parts/和proxy_pass http://apache-parts/都带尾斜杠,Nginx会自动把/parts/后面的URI部分传递给Apache,比如/parts/foo会被代理到http://apache-parts/foo,完美匹配后端应用的根路径。

方式二:用rewrite手动调整URI

如果不想用带尾斜杠的location,可以通过rewrite剥离前缀:

location /parts {
    rewrite ^/parts(.*)$ $1 break;
    proxy_pass http://apache-parts;
    # 同样添加代理头
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

2. 解决应用资源路径的适配问题

很多应用是基于根路径开发的,比如CSS/JS用绝对路径引用(/css/style.css),当代理到/parts下时,浏览器会直接请求/css/style.css(走到Nginx的根location),而不是/parts/css/style.css,导致页面样式/脚本加载失败。

解决办法两种:

方法一:修改应用代码(推荐)
  • 如果是静态站点:把所有绝对路径改成相对路径,或者在HTML头部添加<base href="/parts/">,让浏览器自动给资源路径加上前缀。
  • 如果是动态应用(比如PHP、Python框架):配置应用的base URL为/parts,让框架生成的所有链接自动带上前缀。
方法二:用Nginx的sub_filter替换响应内容

如果没法修改应用代码,可以让Nginx自动替换响应里的根路径前缀:

location /parts/ {
    proxy_pass http://apache-parts/;
    proxy_set_header Host $host;
    # 替换响应中的绝对路径为/parts开头
    sub_filter 'href="/' 'href="/parts/';
    sub_filter 'src="/' 'src="/parts/';
    sub_filter_once off; # 替换所有匹配项,不是只替换第一个
}

注意:这个功能需要Nginx编译了ngx_http_sub_module模块,官方的Nginx镜像默认已经包含。

3. 完整配置示例(Docker Compose + Nginx)

docker-compose.yml

version: '3.8'
services:
  nginx-proxy:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - apache-root
      - apache-parts
      - apache-wiki

  apache-root:
    image: httpd:alpine
    volumes:
      - ./root-app:/usr/local/apache2/htdocs/

  apache-parts:
    image: httpd:alpine
    volumes:
      - ./parts-app:/usr/local/apache2/htdocs/

  apache-wiki:
    image: httpd:alpine
    volumes:
      - ./wiki-app:/usr/local/apache2/htdocs/

nginx.conf

events {}

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

    server {
        listen 80;
        server_name localhost;

        # 代理根路径到apache-root
        location / {
            proxy_pass http://apache-root/;
            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;
        }

        # 代理/parts到apache-parts
        location /parts/ {
            proxy_pass http://apache-parts/;
            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
            # sub_filter 'href="/' 'href="/parts/';
            # sub_filter 'src="/' 'src="/parts/';
            # sub_filter_once off;
        }

        # 代理/wiki到apache-wiki
        location /wiki/ {
            proxy_pass http://apache-wiki/;
            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
            # sub_filter 'href="/' 'href="/wiki/';
            # sub_filter 'src="/' 'src="/wiki/';
            # sub_filter_once off;
        }
    }
}

4. 测试与排查

  • 用curl测试代理是否生效:curl http://localhost/parts/,看返回内容是否和直接访问Apache容器一致。
  • 如果还是有问题,查看Nginx日志:docker logs nginx-proxy,根据日志里的错误信息(比如404、502)进一步排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:34:40