如何使 docker-comose 绑定容器只在已定义的网络上而不是0.0.0.0?

在最近的版本中,docker-compose会自动为它创建的服务创建一个新的网络。基本上,每个 docker-compose设置都有自己的 IP 范围,所以理论上我可以使用预定义的端口在网络的 IP 地址上调用我的服务。这在同时开发多个项目时非常好,因为这样就不需要更改 docker-compose.yml中的端口(也就是说,我可以在不同接口的端口8080上同时运行多个 nginx项目)

但是,这并不按预期的方式工作: 每个暴露的端口仍然在0.0.0.0上公开,因此与多个项目存在端口冲突。将绑定 IP 放入 docker-compose.yml是可能的,但是这对于可移植性来说是一个杀手——并不是团队中的每个开发人员都使用相同的操作系统或在相同的项目中工作,因此不清楚配置哪个 IP。

根据为这个特定项目创建的网络来定义将容器绑定到的 IP 非常好。docker-compose应该知道它创建的是哪个网络,以及它的 IP,所以这应该不是一个问题,但我不能找到一个简单的方法来做到这一点。是否有一种方法,或者这种方法还有待实施?

编辑: 端口冲突的一个例子: 想象两个项目,每个项目都有一个运行在端口8080上的应用服务器和一个运行在端口3306上的 MySQL 数据库,它们分别暴露为“8080:8080”和“3306:3306”。使用 docker-compose运行第一个协议将创建一个名为 app1_network的网络,其 IP 范围为172.18.0.0/16。每个暴露的端口都暴露在0.0.0上,即在127.0.0.1上,在 WAN 地址上,在缺省桥上(172.17.0.0.16) ,也暴露在172.18.0.0.16上。在这种情况下,我可以访问 $WAN_IP:8080上所有127.0.0.1:8080.172.17.0.1:8080.172.18.0.1:8080和 als 的应用服务器。如果我现在启动第二个应用程序,它将启动第二个网络 app2_network172.19.0.0/16,但仍然尝试绑定所有接口上的每个公开端口。这些端口当然已经被占用了(172.19.0.1除外)。如果有可能将每个应用程序限制在其网络中,那么应用程序1将在172.18.0.1:8080和172.19.0.1:8080处可用,而且我不需要将端口映射分别更改为8081和3307来同时运行这两个应用程序。

86063 次浏览

You can publish a port to a single IP address on the host by including the IP before the ports:

docker run -p 127.0.0.1:80:80 -d nginx

The above runs nginx on the loopback interface. You can use a similar port mapping inside of a docker-compose.yml file. e.g.:

ports:
- "127.0.0.1:80:80"

docker-compose doesn't have any special abilities to infer which network interface to use based on the docker network. You'd need to specify the unique IP address to use in each compose file, and that IP needs to be for a network interface on your host. For a developer machine, that IP may change as DHCP gives the laptop/workstation new addresses.

Because of the difficulty implementing your goal, most would either map different ports on the host to different containers, so 13307:3307 for container a, 23307:3307 for container b, 33307:3307 for container c, or whatever number scheme makes sense for you. And when dealing with HTTP traffic, then using a reverse proxy like traefik often makes the most sense.

In your service configuration, in docker-compose.yml:

ports:
- "127.0.0.1:8001:8001"

Reference: https://github.com/compose-spec/compose-spec/blob/master/spec.md#ports

It can be achieved by configuring network in docker-compose file.

Please consider below two docker-compose files. There is still drawback of needing to specify subnet unique across all project you work on at the same time. On the other hand you need to know which service you connecting too - this is why it cannot assign it dynamically.

my-project.yaml:

services:
nginx:
networks:
- my-project-network
image: nginx
ports:
- 80:80


networks:
my-project-network:
driver_opts:
com.docker.network.bridge.host_binding_ipv4: "172.20.0.1"
ipam:
config:
- subnet: "172.20.0.0/16"

my-other-project.yaml

services:
nginx:
networks:
- my-other-project-network
image: nginx
ports:
- 80:80


networks:
my-other-project-network:
driver_opts:
com.docker.network.bridge.host_binding_ipv4: "172.21.0.1"
ipam:
config:
- subnet: "172.21.0.0/16"

Note: that if you have other service binding to *:80 like for instance apache running on host - it will also bind on docker-compose networks' interfaces and you will not be able to use this port.

To run above two services:

docker-compose -f my-project.yaml up -d
docker-compose -f my-other-project.yaml up -d