Nginx反向代理Docker容器时site2静态资源404的解决方法
解决Nginx反向代理中site2静态资源404的问题
我完全懂你的困扰——想保留静态资源的缓存、日志优化规则,但site2的静态资源一直返回404。问题出在你当前的静态资源location块逻辑里:当请求/site2/css/style.css这类资源时,你通过if判断把请求转发到production-site2,但没有去掉/site2这个前缀,导致site2容器收到的请求路径是/site2/css/style.css,而容器内的资源实际是放在/css/style.css(对应容器根路径),自然找不到资源返回404。
下面是修正后的配置,既能保留静态资源的优化规则,又能正确路由site2的静态资源:
server { listen 80 default_server; server_name _; location ~ /\. { deny all; } # 优先匹配site2的静态资源,捕获/site2后的路径转发给容器 location ~* ^/site2/(.+\.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv))$ { proxy_pass http://production-site2/$1; expires 7d; access_log off; } # site2的svg、字体资源处理 location ~* ^/site2/(.+\.(?:svgz?|ttf|ttc|otf|eot|woff|woff2))$ { proxy_pass http://production-site2/$1; add_header Access-Control-Allow-Origin "*"; expires 7d; access_log off; } # 主站的静态资源规则 location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { proxy_pass http://production-site1; expires 7d; access_log off; } # 主站的svg、字体资源规则 location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff|woff2)$ { proxy_pass http://production-site1; add_header Access-Control-Allow-Origin "*"; expires 7d; access_log off; } gzip on; gzip_comp_level 2; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 256; gzip_buffers 16 8k; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; gzip_disable "MSIE [1-6]\.(?!.*SV1)"; gzip_vary on; location / { proxy_pass http://production-site1/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /site2 { proxy_pass http://production-site2/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
关键修改说明:
- 把site2的静态资源规则单独拆分,用
^/site2/(.+)正则捕获/site2之后的资源路径,再通过proxy_pass http://production-site2/$1把去掉前缀后的路径传给容器,这样容器就能匹配到正确的资源路径了。 - 利用Nginx的location匹配优先级(更具体的正则会先被匹配),避免了之前用
if带来的意外行为(Nginx的if在很多场景下会有逻辑陷阱,尽量少用)。
如果你觉得重复写两次静态资源后缀太冗余,也可以用map简化配置:
# 提前定义静态资源对应的后端和路径 map $request_uri $static_backend { ~^/site2/ http://production-site2; default http://production-site1; } map $request_uri $static_path { ~^/site2/(.+) $1; default $request_uri; } server { # ... 其他配置不变 location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { proxy_pass $static_backend/$static_path; expires 7d; access_log off; } location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff|woff2)$ { proxy_pass $static_backend/$static_path; add_header Access-Control-Allow-Origin "*"; expires 7d; access_log off; } # ... 其他配置不变 }
这种方式用map提前定义好后端地址和处理后的路径,让配置更简洁,核心原理和上面一致——都是去掉site2的前缀后转发请求。
测试时可以用curl -I http://example.com/site2/css/style.css查看响应头,确认是否返回200,也可以查看Nginx日志验证请求是否正确转发到site2容器的对应路径。
内容的提问来源于stack exchange,提问作者Pedro Alves
相关产品推荐
相关产品推荐

