实际上,Docker Compose 的等效方法是将相同的字符串附加到
extra_hosts
参数(
#Doc)中,如下所示:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
extra_hosts:
- "host.docker.internal:host-gateway"
您可以看到它已成功映射到docker0
接口的IP地址,这里是172.17.0.1
,从容器内部可以看到,例如:
$ docker-compose up -d
$ docker-compose exec postgres bash
接下来,在容器内部执行:
root@5864db7d7fba:/
root@5864db7d7fba:/
Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
(假设主机上没有关闭或限制docker0
接口的IP端口80的防火墙)。
更多相关信息请参见:
https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66
但是...请注意...
警告 ⚠️
这通常会匹配主机上docker0
接口的172.17.0.1
IP。因此,如果您使用Compose文件(而不是使用docker run
)启动容器,则该容器将无限期地依赖于构建Compose服务期间创建的网络。并且此网络将使用形如172.xxx.0.1
的随机网关地址,这肯定与默认的docker网关172.17.0.1
不同,例如可能是172.22.0.1
。
如果您仅明确授权从主机本地服务的端口172.17.0.1
进行连接,这可能会给您带来一些麻烦。
实际上,无法从容器内部ping该服务的端口,正是因为具有不同分配的网关地址(172.22.0.1
)。
因此,由于无法预先知道Compose网络将具有哪个网关地址,我强烈建议您在Compose文件中明智地构建自定义network
定义,例如:
version: '3.9'
networks:
network1:
name: my-network
attachable: true
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
ip_range: 172.18.5.0/24
gateway: 172.18.0.1
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
networks:
- network1
如果需要的话,我建议使用一些IP范围计算器工具,比如http://jodies.de/ipcalc?host=172.18.5.0&mask1=24&mask2=,尤其是在使用CIDR表示法定义范围时。
最后,启动您的容器,并验证新指定的网关地址172.18.0.1
是否已正确使用:
$ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
172.18.0.1
连接到它,安装netcat
并进行验证:
root@9fe8de220d44:/
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
您可能还需要相应地调整防火墙规则和/或本地服务(例如数据库)允许的IP地址。
另一种解决方案
是使用docker network
连接到现有的默认bridge
网络。为此,在启动容器后,运行以下命令:
$ docker network connect bridge tmp_postgres_1
现在,检查应该会给你两个IP地址:一个是你设置的(如果有),或者是Docker在容器创建期间自动设置的IP地址,另一个是
bridge
IP地址:
$ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
172.17.0.1 172.18.0.1
或者
您可以跳过手动创建网络,直接在Compose服务定义中使用以下network_mode:
标志,告知加入bridge
网络:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
network_mode: bridge
extra_hosts:
- "host.docker.internal:host-gateway"
现在,无论您是使用docker network connect...
方法还是在Compose文件中使用network_mode:
标志,您通常都可以成功加入默认的bridge
网络,并与网关172.17.0.1
连接。这将允许您使用该网关IP连接到主机,无论是通过输入其数字值还是(如果设置了)变量host.docker.internal
:
root@9fe8de220d44:/
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
root@9fe8de220d44:/
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
root@9fe8de220d44:/
Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
⚠️但是,加入“桥接”网络后,您的容器也可以与该网络上的所有其他容器进行通信(如果它们已经发布了端口),反之亦然。因此,如果您需要将其与这些其他容器清楚地分开,请最好不要这样做,并坚持使用其自己的自定义网络!
如果出现问题怎么办?
如果您在尝试后弄乱了docker网络,则可能会遇到以下错误消息:
Creating tmp_postgres_1 ... error
ERROR: for tmp_postgres_1 Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist
ERROR: for postgress Cannot start service postgres: failed to create endpoint tmp_postgres_1 on network bridge: network 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486 does not exist
ERROR: Encountered errors while bringing up the project.
尽管 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486
桥接网络确实存在,但你必须通过重新启动计算机或在最幸运的情况下使用以下命令清除所有内容:
docker service
$ sudo service docker restart
执行 docker networkd prune -f
可能不足以解决问题。
更多文档详见:
https://docs.docker.com/compose/networking/
https://docs.docker.com/compose/compose-file/compose-file-v3/#networks
https://github.com/compose-spec/compose-spec/blob/master/spec.md#networks-top-level-element
这里提供更多的文档链接,以便了解有关Docker Compose网络和文件格式的更多信息。请点击以上链接查看详情。
在具备以下规格的主机上进行了测试:
Ubuntu: 18.04.6 LTS
Kernel: 5.4.0-94-generic
Docker: 20.10.12,构建版本 e91ed57
Docker Compose: 1.27.4,构建版本 40524192
networks
,要么是network_mode
,你说得对。谢谢你的警觉性。我已经修复了。 - swiss_knightpostgresql.conf
中将其添加到listen_addresses
中。 - smidolive-restore: false
,否则在 Linux 下似乎无法使用host.docker.internal
。 - Melroy van den Berg