Docker容器内如何通过服务名访问NGINX配置的子域名站点
嘿,这个场景我太熟悉了!问题的核心在于Docker内部服务的DNS解析规则和Nginx虚拟主机依赖Host头匹配这两点的冲突,咱们直接上可行的解决方案:
方案1:用curl指定Host头(最快最直接)
你不需要改任何配置,只需要在curl请求里手动指定Nginx虚拟主机需要的Host头就行。因为Nginx是根据请求的Host字段来判断应该路由到哪个站点的,你用http://nginx访问时,Host头默认是nginx,所以匹配到了主站;现在要访问api.localhost的站点,只需要把Host头改成api.localhost:
curl -H "Host: api.localhost" http://nginx
这样Nginx就会正确把请求路由到/api对应的Laravel项目了。
方案2:给Nginx服务添加DNS别名(无需修改curl命令)
如果你不想每次curl都加Host头,可以在docker-compose.yml里给nginx服务添加一个aliases配置,让Docker内部的DNS把api.localhost解析到nginx容器的IP:
services: nginx: # 你的其他配置... networks: default: aliases: - api.localhost
修改后重启docker-compose,之后在base容器里直接执行curl http://api.localhost就能正常访问了——因为Docker DNS现在会把api.localhost指向nginx容器,同时请求的Host头也是api.localhost,刚好匹配你Nginx里的虚拟主机配置。
方案3:修改Nginx配置,兼容服务名访问
如果你想直接用http://api.nginx这种形式访问,可以修改Nginx的虚拟主机配置,把api.nginx也加入到server_name列表里:
server { listen 80; server_name api.localhost api.nginx; # 新增api.nginx root /api/public; # 你的其他Laravel相关配置... }
然后在base容器里执行curl http://api.nginx——不过这里要注意,Docker DNS只会解析服务名nginx,所以api.nginx本身不会被自动解析,你还需要在base容器的/etc/hosts里加一行映射(或者在docker-compose的base服务里配置extra_hosts):
services: base: # 你的其他配置... extra_hosts: - "api.nginx:nginx"
这样base容器里就能把api.nginx解析到nginx服务的IP了。
为什么原来的访问方式不行?
给你捋清楚背后的原因:
http://api.nginx:Docker内部DNS只认识服务名(比如nginx),api.nginx不是注册的服务名,所以解析失败。http://api.localhost:base容器默认的hosts里没有把api.localhost指向nginx容器的IP,所以请求发不出去。http://localhost:每个容器的localhost都是自己的回环地址,不是nginx容器的IP,自然访问不到。
内容的提问来源于stack exchange,提问作者user9874638

