[英]docker-compose: open port in container but not bind it from host
I created a service (a small web server) using docker-compose
.我使用
docker-compose
创建了一个服务(一个小型 web 服务器)。 The network part is defined as网络部分定义为
services:
service:
image: ... (this image uses port 9000)
ports:
- 9000:9000
networks:
default:
name: my-network
After docker-compose up
, I observe:在
docker-compose up
之后,我观察到:
127.22.0.1
and the client gets 127.22.0.2
.127.22.0.1
,客户端获得127.22.0.2
。ping 127.22.0.2
.ping 127.22.0.2
成功 ping 客户端。127.22.0.1:9000
127.22.0.2:9000
localhost:9000
192.168.0.10:9000
(This is the host's IP address in the LAN) 192.168.0.10:9000
(这是局域网中主机的IP地址) Now I want to restrict the access from the host using 127.22.0.2:9000
only.现在我想仅使用
127.22.0.2:9000
限制来自主机的访问。 I feel this should be possible if I don't bind the container's 9000 port to the host's 9000 port.如果我不将容器的 9000 端口绑定到主机的 9000 端口,我觉得这应该是可能的。 Then I deleted the
ports: 9000:9000
part from the docker-compose.yml
.然后我从
docker-compose.yml
中删除了ports: 9000:9000
部分。 Now I observe:现在我观察到:
127.22.0.2:9000
127.22.0.2:9000
127.22.0.2
127.22.0.2
从主机 ping 客户端I think: since the the host and the container are both in a bridge network my-network
and have obtained their IP addresses.我认为:由于主机和容器都在桥接网络
my-network
中,并且已经获得了它们的 IP 地址。 The web server should still be reachable from 127.22.0.2:9000
. web 服务器应该仍然可以从
127.22.0.2:9000
访问。 But this is not the case.但这种情况并非如此。
My questions:我的问题:
127.22.0.0/16
be able to talk to each other freely?127.22.0.0/16
中的主机/容器不应该能够自由地相互交谈吗?Docker is also playing with your host iptables in order to achieve its isolation standarts. Docker 也在使用您的主机 iptables 以实现其隔离标准。
These are the default iptables rules with no container running:这些是没有容器运行的默认 iptables 规则:
$ sudo iptables-save
# Generated by iptables-save v1.8.4 on Tue Jan 11 13:11:52 2022
*filter
:INPUT ACCEPT [49:15900]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [53:4709]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Tue Jan 11 13:11:52 2022
# Generated by iptables-save v1.8.4 on Tue Jan 11 13:11:52 2022
*nat
:PREROUTING ACCEPT [3:1112]
:INPUT ACCEPT [3:1112]
:OUTPUT ACCEPT [11:899]
:POSTROUTING ACCEPT [11:899]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Tue Jan 11 13:11:52 2022
After running a container which binds on port 8080 you can see that 3 rules where added to my iptables rules:运行绑定到端口 8080 的容器后,您可以看到 3 条规则添加到我的 iptables 规则中:
$ sudo iptables-save
# Generated by iptables-save v1.8.4 on Tue Jan 11 13:14:36 2022
*filter
:INPUT ACCEPT [79:25192]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [75:8565]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Tue Jan 11 13:14:36 2022
# Generated by iptables-save v1.8.4 on Tue Jan 11 13:14:36 2022
*nat
:PREROUTING ACCEPT [33:4634]
:INPUT ACCEPT [9:3254]
:OUTPUT ACCEPT [13:2363]
:POSTROUTING ACCEPT [13:2363]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:8080
COMMIT
# Completed on Tue Jan 11 13:14:36 2022
So regarding question1: The reason your host/container can't talk to each other freely eventhough they are in the same subbet 127.22.0.0/16 is because of the iptables preventing it.所以关于问题1:您的主机/容器即使在同一个子赌注 127.22.0.0/16 中也不能自由交谈的原因是因为 iptables 阻止了它。
Regarding question2: You can play with docker iptables configuration in order to achieve your wanted behaviour.关于问题2:您可以使用 docker iptables配置来实现您想要的行为。 But IMO you should just bind port 9000 only on localhost instead see , that way it won't listen on your LAN
但是 IMO 你应该只在 localhost 上绑定端口 9000 而不是看到,这样它就不会在你的 LAN 上监听
Your understanding of the networking is correct.您对网络的理解是正确的。 Removing the port binding from the
docker-compose.yml
will remove the exposed port from the host.从
docker-compose.yml
中删除端口绑定将从主机中删除暴露的端口。 Since the host is also part of the virtual network my-network
with an IP in the same subnet as the container, your service should be reachable from the host using the container IP directly.由于主机也是虚拟网络
my-network
的一部分,其中 IP 与容器位于同一子网中,因此您的服务应该可以直接使用容器 IP 从主机访问。
But I think, this is actually a simple typo and instead of但我认为,这实际上是一个简单的错字,而不是
127.22.0.0/16
you actually have你实际上有
172.22.0.0/16
as the subnet for my-network
!作为
my-network
的子网! This is a typical subnet used by docker
in the default configuration, while 127.0.0.0/8
is always bound to the loopback device !这是
docker
在默认配置中使用的典型子网,而127.0.0.0/8
始终绑定到环回设备!
So connecting to 127.22.0.2
will actually connect you to localhost
- which is consistent with the symptoms you encountered:因此,连接到
127.22.0.2
实际上会将您连接到localhost
- 这与您遇到的症状一致:
127.22.0.2:9000
will work only if the port is exposed on the host127.22.0.2:9000
才有效127.22.0.2
since it is the loopback address127.22.0.2
因为它是环回地址
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.