docker - 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 操作。这意味着必须已建立连接。
为什么我不能从我的前端连接到我的烧瓶服务器?
解决方案
我们在评论中发现了几件事。首先,您遇到了代理问题,阻止了一个容器在另一个容器中使用 API。
其次,至关重要的是,您发现 Docker Compose 配置文件中的服务名称在 Docker 设置的虚拟网络系统中可用。front
因此,您可以从ping 通back
,反之亦然。重要的是,值得注意的是,您可以这样做,因为它们位于同一个虚拟网络上,mynet
. 如果它们在不同的 Docker 网络上,那么根据设计,DNS 名称将不可用,并且虚拟容器 IP 地址将无法访问。
顺便说一句,由于您的所有容器都在同一个网络上,并且您没有更改任何网络设置,因此您现在可以放弃该网络。换句话说,您可以删除networks
定义和对它的三个容器引用,因为它们可以直接加入默认网络。
第三,您了解到 Docker 的虚拟 DNS 条目在主机上不可用,因此front
在back
此处不可用。即使是(例如,如果在 hosts 文件中手动输入)这些 IP 也不会工作,因为没有从主机到容器的直接网络路由。
相反,这些容器由 Docker 设备公开,该设备代理从自定义 localhost 端口到这些容器(在您的情况下为 4200、5000 和 5001)的连接。
一个好的临时解决方案是将前端加载到http://localhost:4200
并将其 API 地址硬连接为http://localhost:5000
. 不过,您可能会遇到一些 CORS 问题,因为浏览器会将它们视为不同的服务器。
此外,如果您上线,您可能会遇到移动网络和公司防火墙的一些问题——您可能希望您的前端应用程序位于端口 443,但由于它是一个单独的服务器,您需要为您的服务器使用不同的 IP 地址API,因此它也可以继续使用 443,否则您将需要使用另一个端口。一个干净的解决方案是在两个容器前面放置一个前端代理,然后在 Docker 中公开代理。这会将 HTTP 请求从外部发送到正确的容器,具体取决于您设置的过滤条件。我为此推荐 Traefik,但毫无疑问还有其他几种方法。
推荐阅读
- android - 如何从名称中检索 Android 资源(在 Kotlin 中)?
- vb.net - 我应该如何发送我使用 DataGridViewCellFormattingEventArgs 的 DataGrid 结果
- yii2 - Yii2:在注册模型中添加分配角色
- makefile - Boost.Python Makefile 到 CMakLists.txt
- c# - 在统一中,asmdef 不能引用 Assembly-CSharp
- c++ - 如何使用 lambda 作为 std::unique_ptr 的删除器?
- html - 数据未从 HTML 表更新到 Excel
- sql - sql查询,它查找某些数据所在的每个组中有多少行
- dart - 如果更改返回值类型为什么不更改页面
- regex - 匹配全部大写或全部小写正则表达式的单词列表