目录
当你有两个不同的服务同时使用 Compose 部署,而这两个服务又需要相互通信时,你通常有三种方式来实现它们之间的连接:
host.docker.internal
Docker 提供了一个特殊的 DNS 名称 host.docker.internal
,可以在容器中使用它来访问宿主机上的服务。
因此,你可以在不开放主机防火墙端口的情况下使用这个路径访问宿主机服务,你只需要确保互访的两个容器均暴露了需要访问的端口即可。
但!这个功能仅在 Docker Desktop 上可用,Linux Docker CE 用户需要使用其他方法。
使用外部网络
这是最为无脑,安全性也相应较低的方法。你只需要暴露需要互访的两个容器的端口,同时,开放主机的防火墙对应端口,随后在容器中使用主机网卡的 IP 地址进行访问即可。
使用自定义网络
这就是本文要介绍的方法了,通过将需要的服务同时连接到一个 Docker 网络中,你可以实现它们之间的直接通信,而无需暴露主机端口。
假设你有这样的两个服务,你需要让服务 2 中的 app
能够访问到服务 1 中的 app1
。
服务 1 中的 app1
与 db
之间也需要互相通信,但你不需要服务 2 能够访问 db
。
两个初始的 docker-compose.yml
version: '3'services: app1: image: app1 db: image: postgres:latest
version: '3'services: app: image: app-xxx
你只需要首先创建一个网络:
docker network create my-network
然后为两个 Compose 中需要互访的容器添加网络:
version: '3'services: app1: image: app1 networks: - default - my-network db: image: postgres:latest
networks: my-network: external: true
version: '3'services: app: image: app-xxx networks: - default - my-network
networks: my-network: external: true
现在,你可以在 app
中通过 app1
的服务名来访问服务 1 中的 app1
,而不需要暴露任何主机端口。为设置了自定义网络的容器显式配置 default
网络是必要的(除非你在 Compose 中预先设置过服务间的网络通信,不使用默认 Docker 网络),不配置会导致配置了自定义网络的容器没有连接到默认 Compose 网络,而无法相互访问。