首页 > 解决方案 > Docker-compose:Docker 容器无法使用服务名称进行连接

问题描述

我有 3 个容器。一个是提供静态内容的 lighttpd 服务器(前端)。我有 2 个烧瓶服务器处理后端(后端模型

这是我的 docker-compose.yml

version: "3"
services:
  front:
    image: ecd3:latest
    ports:
      - 4200:80
    tty: true
    links:
      - "back"
    depends_on:
      - back
    networks:
      - mynet

  back:
    image: esd3:latest
    ports:
      - 5000:5000
    links:
      - "model"
    depends_on:
      - model
    networks:
      - mynet

  model:
    image: mok:latest
    ports:
      - 5001:5001
    networks:
      - mynet

networks:
  mynet:

我正在尝试从我的前端(前端)向我的烧瓶服务器(后端)发送一个 http 请求。我已将烧瓶服务器绑定到 0.0.0.0,甚至在前端使用了服务名称(http://back:5000/endpoint

尝试在前端容器内卷曲烧瓶服务器(curl back:5000)给了我这个:

curl: (52) Empty reply from server

从前端容器内部对烧瓶服务器执行 ping 操作。这意味着必须已建立连接。

为什么我不能从我的前端连接到我的烧瓶服务器?

标签: dockerflasknetworkingdocker-compose

解决方案


我们在评论中发现了几件事。首先,您遇到了代理问题,阻止了一个容器在另一个容器中使用 API。

其次,至关重要的是,您发现 Docker Compose 配置文件中的服务名称在 Docker 设置的虚拟网络系统中可用。front因此,您可以从ping 通back反之亦然。重要的是,值得注意的是,您可以这样做,因为它们位于同一个虚拟网络上,mynet. 如果它们在不同的 Docker 网络上,那么根据设计,DNS 名称将不可用,并且虚拟容器 IP 地址将无法访问。

顺便说一句,由于您的所有容器都在同一个网络上,并且您没有更改任何网络设置,因此您现在可以放弃该网络。换句话说,您可以删除networks定义和对它的三个容器引用,因为它们可以直接加入默认网络。

第三,您了解到 Docker 的虚拟 DNS 条目在主机上不可用,因此frontback此处不可用。即使是(例如,如果在 hosts 文件中手动输入)这些 IP 也不会工作,因为没有从主机到容器的直接网络路由。

相反,这些容器由 Docker 设备公开,该设备代理从自定义 localhost 端口到这些容器(在您的情况下为 4200、5000 和 5001)的连接。

一个好的临时解决方案是将前端加载到http://localhost:4200并将其 API 地址硬连接为http://localhost:5000. 不过,您可能会遇到一些 CORS 问题,因为浏览器会将它们视为不同的服务器。

此外,如果您上线,您可能会遇到移动网络和公司防火墙的一些问题——您可能希望您的前端应用程序位于端口 443,但由于它是一个单独的服务器,您需要为您的服务器使用不同的 IP 地址API,因此它也可以继续使用 443,否则您将需要使用另一个端口。一个干净的解决方案是在两个容器前面放置一个前端代理,然后在 Docker 中公开代理。这会将 HTTP 请求从外部发送到正确的容器,具体取决于您设置的过滤条件。我为此推荐 Traefik,但毫无疑问还有其他几种方法。


推荐阅读