[英]What is the equivalent of --add-host=host.docker.internal:host-gateway in a Compose file
Starting from Docker version 20.10
( https://github.com/moby/moby/pull/40007 ), there is a new special string host-gateway
that one can use within the --add-host
run flag to allow a direct connection from inside a docker container to the local machine on Linux based systems.从 Docker 版本20.10
( https://github.com/moby/moby/pull/40007 ) 开始,有一个新的特殊字符串host-gateway
可以在--add-host
运行标志中使用以允许直接连接从 docker 容器内部到基于 Linux 的系统上的本地计算机。 And this is very nice.这是非常好的。
But what is the equivalent of --add-host=host.docker.internal:host-gateway
in a Compose file?但是 Compose 文件中的--add-host=host.docker.internal:host-gateway
的等价物是什么?
eg in:例如在:
$ docker run \
--rm \
--name postgres \
-p "5433:5432" \
-e POSTGRES_PASSWORD=**** \
--add-host=host.docker.internal:host-gateway \
-d postgres:14.1-bullseye
How would the same --add-host
flag fit in this Docker Compose equivalent template:相同的--add-host
标志如何适合此 Docker Compose 等效模板:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
It's for sure not: network_mode: host
at the service level (see #Doc ).肯定不是: network_mode: host
(请参阅#Doc )。
The actual Docker Compose equivalent is achieved by appending the same string to the extra_hosts
parameters ( #Doc ) as:实际的 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"
You can see it has been successfully mapped to the IP of the docker0
interface, here 172.17.0.1
, from inside your container, eg:你可以看到它已经从你的容器内部成功映射到docker0
接口的 IP ,这里是172.17.0.1
,例如:
$ docker-compose up -d
$ docker-compose exec postgres bash
then, from inside the container:然后,从容器内部:
root@5864db7d7fba:/# apt update && apt -y install netcat
root@5864db7d7fba:/# nc -vz host.docker.internal 80
Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
(assuming port 80 is not closed or constrained to the IP of the docker0
interface by a firewall on the host machine). (假设 80 端口没有被主机上的防火墙关闭或限制为docker0
接口的 IP)。
More on this can be found here:更多信息可以在这里找到:
https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66 https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66
But... beware...但是……小心……
This will normally always match the 172.17.0.1
IP of the docker0
interface on the host machine.这通常将始终与主机上docker0
接口的172.17.0.1
IP 匹配。 Hence, if you spin-up a container using a Compose file (so, not by using docker run
), chances are infinitely high that this container will rely on the network created during the build of the Compose services.因此,如果您使用 Compose 文件启动容器(因此,不是使用docker run
),该容器将依赖于在构建 Compose 服务期间创建的网络的可能性非常高。 And this network will use a random Gateway address of the form 172.xxx.0.1
which will for sure be different than the 172.17.0.1
default docker Gateway, this can for example be 172.22.0.1
.并且该网络将使用172.xxx.0.1
形式的随机网关地址,这肯定不同于172.17.0.1
默认的 docker 网关,例如可以是172.22.0.1
。
This can cause you some troubles if for example you only explicitly authorized connections from 172.17.0.1
to a port of a local service on the host machine.如果您仅明确授权从172.17.0.1
到主机上本地服务的端口的连接,这可能会给您带来一些麻烦。 Indeed, it will not be possible to ping the port of that service from inside the container, precisely because of this differently assigned Gateway address ( 172.22.0.1
).实际上,无法从容器内部 ping 该服务的端口,正是因为这个不同分配的网关地址( 172.22.0.1
)。
Therefore, and because you cannot know in advance which Gateway address the Compose network will have, I highly recommend that you wisely build a custom network
definition in the Compose file, eg:因此,由于您无法提前知道 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
If needed, I also recommend using some IP range calculator tool, such ashttp://jodies.de/ipcalc?host=172.18.5.0&mask1=24&mask2= to help yourself in that task, especially when defining ranges using the CIDR notation.如果需要,我还建议使用一些 IP 范围计算器工具,例如http://jodies.de/ipcalc?host=172.18.5.0&mask1=24&mask2=来帮助自己完成该任务,尤其是在使用CIDR表示法定义范围时。
Finally, spin up your container.最后,启动你的容器。 And verify that the newly specified Gateway address 172.18.0.1
has been correctly used:并验证新指定的网关地址172.18.0.1
是否已正确使用:
$ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
172.18.0.1
Attach to it, install netcat
and verify:附加到它,安装netcat
并验证:
root@9fe8de220d44:/# nc -vz 172.18.0.1 80
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
(you may also need to adapt your firewall rules accordingly and/or the allowed IPs for your local service, eg a database) (您可能还需要相应地调整防火墙规则和/或本地服务允许的 IP,例如数据库)
is to connect to the existing default bridge
network using docker network
.是使用docker network
连接到现有的默认bridge
网络。 In order to do so, after having spin up the container, run this command:为此,在启动容器后,运行以下命令:
$ docker network connect bridge tmp_postgres_1
Now, an inspect should give you two IPs;现在,检查应该给你两个 IP; the one you set up (if any) or the one auto-magically set up by docker during the container creation, and the bridge
IP:您设置的那个(如果有的话)或 docker 在容器创建期间自动设置的那个,以及bridge
IP:
$ docker inspect tmp_postgres_1 -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
172.17.0.1 172.18.0.1
you can skip the manual network creation and directy tell, in your Compose service definition, to join the bridge
network using the networks_mode:
flag as follow:您可以跳过手动网络创建,并在 Compose 服务定义中直接告诉使用networks_mode:
标志加入bridge
网络,如下所示:
version: '3.9'
services:
postgres:
image: postgres:14.1-bullseye
environment:
POSTGRES_PASSWORD: ****
ports:
- "5433:5432"
# removed networks: and add this:
networks_mode: bridge
extra_hosts:
- "host.docker.internal:host-gateway"
Now, whether you used the docker network connect...
method or the network_mode:
flag in your Compose file, you normally succesfully joined the default bridge
network with the Gateway 172.17.0.1
, this will allow you to use that Gateway IP to connect to your host, either by typing its numerical value, or if set, the variable host.docker.internal
:现在,无论您是使用docker network connect...
方法还是您的 Compose 文件中的network_mode:
标志,您通常都会成功地使用网关172.17.0.1
加入默认bridge
网络,这将允许您使用该网关 IP 连接到您的主机,可以通过输入其数值,或者如果设置了变量host.docker.internal
:
root@9fe8de220d44:/# nc -vz 172.18.0.1 80
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
root@9fe8de220d44:/# nc -vz 172.17.0.1 80
Connection to 172.18.0.1 80 port [tcp/http] succeeded!
root@9fe8de220d44:/# nc -vz host.docker.internal 80
Connection to host.docker.internal (172.17.0.1) 80 port [tcp/http] succeeded!
⚠️ But by joining the bridge
network, you also makes it possible for your container to communicate with all other containers on that network (if they have published ports), and vice-versa. ⚠️ 但是通过加入bridge
网络,您还可以让您的容器与该网络上的所有其他容器进行通信(如果它们已发布端口),反之亦然。 So if you need to clearly keep it apart from these other containers, you preferably don't want to do that and stick with its own custom network!因此,如果您需要清楚地将其与这些其他容器分开,您最好不要这样做并坚持使用它自己的自定义网络!
In case you messed up your docker network after some trials, you may face such error message:如果您在经过一些试验后弄乱了您的 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.
even so the 895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486
bridge network does actually exist, you have to clean all that either by restarting your computer or in the luckiest case, the docker service with:即便如此895de42e2a0bdaab5423a6356a079fae55aae41ae268ee887ed214bd6fd88486
网桥网络确实存在,您必须通过重新启动计算机或在最幸运的情况下使用 docker 服务来清除所有这些:
$ sudo service docker restart
(a docker networkd prune -f
may not be sufficient). ( docker networkd prune -f
可能不够用)。
More in the documentation:文档中的更多内容:
https://docs.docker.com/compose/networking/ https://docs.docker.com/compose/networking/
https://docs.docker.com/compose/compose-file/compose-file-v3/.networks 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 https://github.com/compose-spec/compose-spec/blob/master/spec.md.networks-top-level-element
Tested on a host machine having the following specs:在具有以下规格的主机上测试:
Ubuntu: 18.04.6 LTS Ubuntu:18.04.6 LTS
Kernel: 5.4.0-94-generic Kernel:5.4.0-94-通用
Docker: 20.10.12, build e91ed57 Docker:20.10.12,构建 e91ed57
Docker Compose: 1.27.4, build 40524192 Docker 组成:1.27.4,构建 40524192
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.