【问题标题】:How do I access a server on localhost with nginx docker container?如何使用 nginx docker 容器访问 localhost 上的服务器?
【发布时间】:2025-12-22 22:55:11
【问题描述】:

我正在尝试使用 nginx 的 docker 化版本作为我的节点 (ExpressJS) 应用程序的代理服务器。无需对 nginx 进行任何配置并为容器发布端口 80,我就能看到默认的 nginx 登录页面。所以我知道这很有效。

现在我可以挂载包含proxy_pass localhost:3000 配置的启用站点的目录。我的节点应用程序在本地运行(不在任何 Docker 容器中),我可以通过端口 3000(即localhost:3000)访问它。但是,我假设在运行 nginx 容器、映射到端口 80 并代理我的 localhost:3000 的情况下,我将能够看到我的 very 简单(hello world)应用程序。相反,我收到了 502。

我需要向 docker 传递一些东西吗?这可能是 nginx 配置错误吗?这是我的 nginx 配置:

server {
  listen 0.0.0.0:80;
  server_name localhost;

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

我尝试过使用this question,但似乎没有帮助。除非我做错了什么。

【问题讨论】:

  • 我也试过了,但似乎无法让它工作。我知道这个类似的问题已经被问过很多次,甚至我得到的 502 错误也是如此,但这些都没有奏效。我下班回家后会重新检查。
  • DNS ftw,imo。主机有一个名字;)
  • docker on linux, version >= 20.04 可以使用带有运行标志的host.docker.internal;见*.com/a/61424570/2014893

标签: node.js nginx docker


【解决方案1】:

如果您使用 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;
  }
}

【讨论】:

  • 我使用了这个解决方案!谢谢 简单易懂
  • 注意:host.docker.internal 不适用于 linux。
  • 除非你设置extra-hosts*.com/a/43541732/6790541
  • 这在 Windows 10 主机上也适用于我。
【解决方案2】:

你可以得到你当前的IP地址如图here:

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

然后您可以将--add-host 标志与docker run 一起使用:

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

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

【讨论】:

  • 这是正确的,但并不完全适合我。一方面,我在笔记本电脑上工作,所以我提取 ip 的方法明显不同。我尝试使用相同的方法更改en0,但一直使用addr:192.xxx.x.xx 获得结果,所以我最终只是将其硬编码。我将使用什么实用程序来剥离开头addr:,因为前提是它不适用于docker。不过还是谢谢你。我正在为遇到此问题的其他人写此评论。
  • 没关系,我使用sed 来去除开头的addr:。如您所知,我不是管理员 :)
  • 很棒的建议。谢谢,伙计。
【解决方案3】:

是的。 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`

您应该将“192.168.59.3”替换为boot2docker ip 返回的任何内容。

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

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

【讨论】:

    【解决方案4】:

    在 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
    

    然后,您可以使用docker.host.internal,而不是在容器内使用localhost

    【讨论】:

      【解决方案5】:

      最后,如果您使用 Nginx 作为多个服务的反向代理,您可以使用 docker-compose 来旋转所有这些。确保仅在 Nginx 服务上公开端口“80:80”。其他服务您可以只公开服务端口而不映射到底层网络,如下所示:

      web:
      .....
          expose:
             - 8080
      nginx:
      .....
          port:
              - “80:80”
      

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

      【讨论】:

      • 不清楚您在这里所说的我们不需要的“上游应用程序部分”是什么意思。如果http://service-name 是您的外部域而不是本地主机,那么这最终也不是很便携。这是我找到的 localhost 的第一个替代方案,但我不喜欢它,因为我不能确定我的 nginx 重定向实际上不会返回到 Internet 只是为了进入不同的端口。跨度>
      • 请阅读文档,这是一个您应该熟悉的技术术语。 nginx.org/en/docs/http/ngx_http_upstream_module.html
      • 这是一个我熟悉的技术术语,但我不希望每个人都如此,我什至不确定你指的是什么。另外,我不知道您为什么提到它,因为上面没有其他人提到“上游”。我不会将“上游”模块视为初学者功能,因此说“您应该知道这一点”并不是很有趣。这就是 *,人们来这里是因为他们不可能知道所有事情。