如何使用nginx docker容器访问本地主机上的服务器?

62

我正在尝试使用一个经过Docker化的Nginx版本作为我的Node(ExpressJS)应用程序的代理服务器。在没有对Nginx进行任何配置并且为容器发布80端口的情况下,我能够看到默认的Nginx着陆页面。所以我知道这部分是起作用的。

现在我可以挂载包含proxy_pass localhost:3000配置的sites-enabled目录。我有一个本地运行的Node应用程序(不在任何Docker容器中),我可以通过端口3000访问它(即localhost:3000)。然而,我会认为在运行着映射到端口80的Nginx容器,并代理我的localhost:3000的情况下,我将能够看到我的非常简单(hello world)的应用程序。但是我收到了502错误。

我需要在Docker中传递一些内容吗?这可能是Nginx配置错误吗?这是我的Nginx配置:

server {
  listen 0.0.0.0:80;
  server_name localhost;

  location / {
    proxy_pass http://localhost:3000;
  }
}

我试过使用这个问题,但似乎没有帮助。除非我做错了什么。


我也尝试了,但似乎无法让它工作。我知道类似的问题已经被问过很多次,甚至我遇到的502错误也是如此,但那些解决方法都没有奏效。我下班回家后将再次检查。 - adam-beck
DNS很棒,我个人认为。主机有一个名字 ;) - user2105103
在Linux上,版本> =“20.04”的Docker可以使用运行标志host.docker.internal;请参见https://dev59.com/YV0Z5IYBdhLWcg3wiw4w#61424570。 - Robert K. Bell
6个回答

75
如果您使用的是docker-for-mac 18.03或更高版本,它会自动创建一个特殊的DNS条目 host.docker.internal,动态地绑定到主机的inet IP。然后,您可以在容器内使用该dns名称代替localhost来代理在主机上运行的服务。
例如,nginx配置文件:
server {
  listen 0.0.0.0:80;
  server_name localhost;

  location / {
    proxy_pass http://host.docker.internal:3000;
  }
}

1
我使用了这个解决方案!谢谢,它非常简单易用。 - Sergey
10
注意:host.docker.internal 在Linux上无法使用。 - 21rw
4
除非你设置了extra-hosts,否则请参考 https://dev59.com/YV0Z5IYBdhLWcg3wiw4w#43541732。 - 21rw
2
这对我在 Windows 10 主机上也起作用了。 - Joe Sadoski

24

您可以在此处查看如何获取您当前的IP地址:

ifconfig en0 | grep inet | grep -v inet6 | awk '{print $2}'

然后您可以在 docker run 命令中使用 --add-host 标志:

docker run --add-host localnode:$(ifconfig en0 | grep inet | grep -v inet6 | awk '{print \$2}') ...

在您的proxypass中,请使用localnode而不是localhost


1
这个方向是对的,但不完全适合我。首先,我是在笔记本电脑上工作,所以提取IP的方法显然不同。我尝试使用相同的方法更改“en0”,但一直得到“addr:192.xxx.x.xx”的结果,所以最终我只是硬编码了它。我应该使用什么工具来剥离开头的“addr:”,因为提供这个将无法与docker一起使用。谢谢你。我写这条评论是给其他遇到这个问题的人。 - adam-beck
1
没事了,我使用了 sed 命令来去掉开头的 addr:。你可以看出我不是一个系统管理员 :) - adam-beck
太棒了,谢谢伙计。 - Kiknaio

5

是的,Docker需要知道您的主机信息。您可以使用--add-host开关来设置别名。在*nix系统上,如果要将别名设置为"localbox",则应该执行以下操作:

docker run my_repo/my_image --add-host=localbox:<host_name>`

在boot2docker上,应该是这样的:
docker run my_repo/my_image --add-host=localbox:192.168.59.3`

您需要用boot2docker ip返回的IP地址替换 "192.168.59.3"。

然后,您应该始终通过别名 localbox 访问主机,只需更改您的 nginx 配置为:

location / {
  proxy_pass http://localbox:3000;
} 

3
在Linux上,以下方法适用:
在docker-compose.yml文件中,将入口脚本挂载到nginx容器中:
  nginx:
    image: nginx:1.19.2
    # ...
    volumes:
      - ./nginx-entrypoint.sh:/docker-entrypoint.d/nginx-entrypoint.sh:ro

入口点的内容将本地地址映射到主机本地地址。
apt update
apt install iproute2 -y
echo "`ip route | awk '/default/ { print $3 }'`\tdocker.host.internal" >> /etc/hosts

那么,在容器内部,不要使用localhost,而应该使用docker.host.internal


-1

我曾经遇到过同样的问题。通过使用 Docker 主机的本地 IP 地址而不是 localhost 来解决了这个问题。

因此,如果你的 Docker 主机在局域网中的本地 IP 地址为 192.168.2.2:

  location / {
    proxy_pass http://192.168.2.2:3000;
  }

当然,只有在为docker主机分配了静态IP的情况下,这个解决方案才能够很好地发挥作用。


-2
最后,如果您正在使用Nginx作为多个服务的反向代理,您可以使用docker-compose来管理所有这些。请确保仅在Nginx服务上公开端口“80:80”。其他服务只需将服务端口公开,而无需映射到底层网络,如下所示:
web:
.....
    expose:
       - 8080
nginx:
.....
    port:
        - “80:80”

然后使用Nginx配置proxy_pass http://service-name:port,你根本不需要上游应用程序部分


这里的“上游应用程序部分”是什么意思并不清楚,我们不需要它。此外,如果http://service-name是您的外部域而不是本地主机,则这将变得不太可移植。这是我发现的第一个替代本地主机的方法,但我不喜欢它,因为我无法确定我的nginx重定向是否实际上返回到互联网,然后在不同的端口上进入。 - jcairney
请阅读文档,这是一个你应该熟悉的技术术语。http://nginx.org/en/docs/http/ngx_http_upstream_module.html - George Mogilevsky
这是一个我熟悉的技术术语,但我不认为每个人都知道,而且我甚至不确定你提到的就是这个。此外,我不知道你为什么提到它,因为上面没有其他人提到“上游”。我认为“上游”模块并不是初学者功能,所以说“你应该知道这个”并不太公平。这是stackoverflow,在这里人们来的原因是因为他们不可能知道一切。 - jcairney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接