hello云胜

技术与生活

0%

docker网络

端口映射

在启动一个docker容器时,经常指定-p绑定端口。

1
docker run -p 8000:80 --name nginx8000 -d nginx

将主机的8000端口和容器的80端口进行映射

实现的原理就是iptable的nat表中添加相应的规则,将对本机8000端口的访问进行一次dnat操作。转换成对容器ip:容器端口的访问

查看一下本机的iptables

1
iptables -t nat -nL

image-20231011140525875

我们知道docker会创建自定义链DOCKER

然后创建容器如果需要端口映射时,就在里面定义一个DNAT规则

这个DOCKER链被PREROUTING链和OUTPUT链引用。就是在进来和出去的时候都会做dnat

访问外网

默认情况下容器就是可以访问外网的。因为容器的默认网络接口是在docker0网桥上的接口,也就是主机上的本地接口。

只要主机能访问的地址,容器默认就能访问。

其原理是通过Linux系统的转发功能实现的(把主机当交换机)。

如果你的容器不能访问。看看ip_forward是否为1

可以做个实验验证

1
docker exec -it nginx8000 ping 一个ip

发现报错了,因为没有ping命令。

这是我们使用容器经常遇到的一个问题。那怎么办?去容器理安装吗?

其实有个更好的办法

我们之前学过network的4种网络模式,有一个container模式。可以将新容器加到已有容器的网路空间中。

现在我们就可以利用这个特性

1
docker run -it --network container:nginx8000 alpine

启动一个alpine容器,加到nginx8000容器的网络空间下

image-20231011152405931

就可以测试了。是不是很方便

自定义网络cidr

我们说过,docker默认的网段是172.17.0.0/16。可以在启动docker时指定cidr来自定义网段。

注意修改cidr需要保证现在没有运行中的docker。所有最好是启动docker daemon前就做这个。

现在我已经有启动的容器,先全部停掉

然后修改/etc/docker/daemon.json

1
2
3
{
"bip":"172.88.88.1/24"
}

注意bip应该是个有效ip地址。

1
2
3
4
# systemctl stop docker
# ip link set dev docker0 down
# brctl delbr docker0
# systemctl start docker

再启动一个容器看看

1
2
3
4
# docker run -p 8100:80 --name nginx8100 -d nginx
# docker inspect -f "{{ .NetworkSettings.IPAddress }}" nginx8100
172.88.88.2

现在就是我们自定义的cidr段了

新增网络

如果已经启动了很多容器,就不能修改默认的网络了。可以新增一个自己的网络

1
2
# docker network create -d bridge --subnet 166.66.66.0/24 mynet
9d56da8bfe3d233317fff8f623c03a4b74ffaa90b89c7b70821e1f6153385aa7

返回的是网络id

我们创建了一个名为mynet的网络,网段是166.66.66.0/24。使用的网络策略是bridge模式

1
2
3
4
# brctl show
bridge name bridge id STP enabled interfaces
br-9d56da8bfe3d 8000.02424dbc03f4 no
docker0 8000.02426a04ad73 no veth474c3aa

会创建出一个新的网桥br-9d56da8bfe3d

image-20231011171427742

网桥的ip就是166.66.66.1

image-20231011171657885

我们看docker的网络也多了我们的这个

使用

只需要在创建容器时,指定下使用mynet

1
2
3
# docker run -p 8200:80 --name nginx8200 --net mynet -d nginx
# # docker inspect -f "{{ .NetworkSettings.Networks.mynet.IPAddress }}" nginx8200
166.66.66.2