文章目录
- 1. 背景
- 2. 最终目标
- 3. 使用公网IP进行通信(不推荐)
- 4. 使用内网IP进行通信(可以解决大部分人的问题了)
- 5. 使用容器 ID,容器 IP, docker0的 IP,容器名,服务名称,hostname(推荐)进行通信
- 5.1 使用容器 ID(不推荐)
- 5.2 使用容器IP(不推荐)
- 5.3 使用docker0 IP(不推荐)
- 5.4 使用容器名,服务名(推荐)
- 5.5 使用hostname(更推荐)
- 6. 特殊情况:在windows 与 mac 系统中
- 7. 总结一下子:
1. 背景
一个项目(或者服务)由多个子项目(或者微服务)组成的,现行比较方便的是采用 docker 容器来生成微服务, 使用 docker-compose 来编排多个微服务组成整个项目。
这就涉及到了多个微服务之间的通信问题(调用与被调用)本文结合一些实践来说明下在同一台宿主机内,各容器之间的通信。
2. 最终目标
实现一个项目从 A 服务器,迁移到 B 服务器,或迁移到 C 服务器,等更多服务器上, 几乎不用修改配置文件(如修改 IP 啥的)。
3. 使用公网IP进行通信(不推荐)
- 结论: 可以实施,但不推荐。
- 优势:配置起来非常简单。
- 缺点: 容器之间的通信效率最底。如果使用了阿里云等云厂商提供有服务器,则可能会导致流量费用过高。
4. 使用内网IP进行通信(可以解决大部分人的问题了)
- 结论: 可以实施,一次部署完成后,也不迁移的情况下,可以使用。
- 优势:配置难度同公网 IP。
- 缺点:容器之间的通信效率相比公网 IP 提高很多。且不产生流量相关的费用。
- 截止到这里, 已经可以满足大部分人的需求了。
5. 使用容器 ID,容器 IP, docker0的 IP,容器名,服务名称,hostname(推荐)进行通信
5.1 使用容器 ID(不推荐)
- 缺点: 每次新打包后,容器 ID 都不一样,所以非常不推荐。
5.2 使用容器IP(不推荐)
- 缺点:容器 IP 的查找相对比较麻烦。且在不同的宿主机上,容器 IP 不一致。
5.3 使用docker0 IP(不推荐)
- 缺点:docker0 IP 的查找相对比较麻烦。且在不同的宿主机上,docker0 IP 不一致。
5.4 使用容器名,服务名(推荐)
- 容器名和服务名称可以自定义,在 A,B 服务器上迁移时几乎不需要修改配置文件。
- 坑点:
- 容器名,服务名的命名方式,在官方的文档几乎没有要求,但如果使用了容器名或服务名进行容器之间的通信,就需要满足一些应用代码层面的数据类型检查,否则通信不成功。
- 端口号:应使用内网端口号,为啥呢? 请查阅容器之间的通信方式:bridge网络
5.5 使用hostname(更推荐)
- 推荐原因:容器名和服务名称可以自定义,在 A,B 服务器上迁移时几乎不需要修改配置文件。
- 坑点:
-
hostname 命名,在官方文档中,对 hostname 命名格式没有要求,但在服务内部的应用层内,
一些数据类型的检查对 hostname要求是不能带有下划线
。如 python pydantic.Httpurl 的类型检测就会检测不通过。java中同样有此类检查。可以参考的样例有: host.docker.internal(在 windows系统与 mac 系统中,可以使用host.docker.internal
来代替IP 地址,容器名,服务名啥的,这个也挺方便)建议的命名方式,如 mysql,可以将 hostname 命令为:
host.mysql.internal
-
端口号: 容器一般有对外暴露的端口号和内部的端口号。那么容器之间的通信,应该是外部端口号还是内部端口号?
- 答案是: 内部端口号
6. 特殊情况:在windows 与 mac 系统中
可以使用 host.docker.internal
代替容器之间的通信IP。
7. 总结一下子:
通过以上推荐一定是达到了 在 win, mac, linux三种环境下,不需要修改配置文件的目标了吗?
不是的, 但是达到了 90%。 剩余 10%是由项目应用决定的。
举个例子:
如果项目中有个自定义的 minio服务, 那么生成 minio 服务的accessKey和secretKey,需要手动的进行生成。然后再更新到项目的配置文件中。这个过程,我还没有实现完全的自动化。