Docker Compose下Nginx配置疑问:API网关方案及404异常解决
这种Nginx动态路由方式作为API网关是否可行?
完全可行,这种方案适配中小规模的Docker服务集群,借助Nginx高性能反向代理能力+Docker内置DNS实现动态服务路由,优势是轻量、资源消耗低、配置简单,无需额外部署服务发现组件(Docker DNS已完成服务名解析工作)。但它也有局限性:像限流、熔断这类复杂流量控制,以及精细权限管控、服务健康检查等高级功能,不如Kong、APISIX这类专业API网关完善。如果你的场景仅需简单的API路由转发,这个方案完全够用。
偶现404问题的排查与解决方法
你遇到的偶现404、一段时间后自动恢复的情况,大概率和DNS缓存过期、路由路径匹配、服务启动顺序这几个因素相关,对应解决方法如下:
1. 优化DNS解析配置,解决服务IP变更后的缓存问题
Docker容器重启或重新部署时,服务IP会发生变化,但Nginx默认会缓存DNS解析结果。你已配置resolver 127.0.0.11 valid=30s,可进一步优化:
- 缩短缓存有效期:将
valid=30s改为valid=10s,让Nginx更快刷新DNS记录 - 添加DNS查询超时:增加
resolver_timeout 5s;,避免DNS查询卡顿导致请求失败 - 开启代理重试:在
proxy_settings.conf或对应location块中添加proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;,当Nginx连接后端失败时自动重试(多实例场景更有效)
2. 修正路由匹配规则,避免路径不匹配导致的404
你的location正则末尾带有/(比如^/v1/system/(?<service_name>[^/]+)/),这意味着只有请求路径末尾带/(如/v1/system/user/)或后续有子路径(如/v1/system/user/api)才会匹配;若请求为/v1/system/user(不带末尾/),会直接进入默认location代理到x7:8000,而x7无对应资源则返回404。
修改正则规则,确保匹配所有前缀为/v1/system/xxx的请求,同时传递正确路径给后端:
location ~ ^/v1/system/(?<service_name>[^/]+)(/.*)?$ { # 移除前缀/v1/system/xxx,仅将后续路径传递给后端服务 rewrite ^/v1/system/[^/]+(/.*)$ $1 break; proxy_pass http://$service_name:8080; include /etc/nginx/conf.d/proxy_settings.conf; }
同理,/v1/hlj/对应的location块做相同修改,保证所有符合前缀的请求都能正确路由到对应服务。
3. 调整服务启动顺序,避免Nginx先启动导致的解析失败
若Nginx在后端服务之前启动,此时Docker DNS尚未注册后端服务记录,Nginx解析服务名会失败,返回404;等后端服务启动后,DNS缓存更新就会恢复正常。
解决方法:
- 在Docker Compose中给Nginx添加
depends_on,确保后端服务优先启动:
注意:services: nginx: depends_on: - service1 - service2 - x7depends_on仅保证启动顺序,不确保服务完全就绪;若需严格等待服务就绪,可使用wait-for-it这类脚本,让Nginx等后端服务端口开放后再启动。
4. 检查404页面的存在性
你的配置指定了error_page 404 /404.html,需确保Nginx容器内的/etc/nginx/conf.d/目录下确实存在404.html文件;若不存在,Nginx会返回默认404页面,甚至出现“404页面不存在”的错误提示。
内容的提问来源于stack exchange,提问作者Frank AK

