本文提出了一种可以解决使用 docker compose 的容器其默认网段172.17.0.0/16与实际网络环境网段冲突问题的方法——重建网桥。
0x00 引言
为了方便校内举行算法编程比赛,我们在学校服务器上通过 docker compose 搭建了一个OJ,平常使用都没有问题,但有一次在学校综合教学楼B区机房组织进行比赛的时候,发现登不上去,ping服务器也ping不通,只能走WebVPN访问。
在和信网处的老师确认过B区机房可以正常访问服务器的网关后,我和老师确认是因为docker服务造成的网段冲突问题。
0x01 学校的网络结构
我们学校的网络结构大概如下(仅作原理说明,非真实链路结构):
机房的每一台电脑会连接到机房后面的交换机上,机房后面的交换机会和这栋楼的交换机相连接,然后与学校数据中心的主交换机连接。
学校数据中心的主交换机还连接着互联网。
同时,学校的数据中心还放着其他服务器。每台服务器都连着它所在的机柜的交换机,机柜的交换机与服务器管理交换机连接,然后与数据中心的主交换机连接。
然后,服务器会因为docker服务而在路由表上加入连接容器的虚拟网段和网关。
0x02 故障原因
简单来说,就是机房电脑的网段为172.17.0.0/16,而docker的默认网段也为172.17.0.0/16。
比如我将OJ搭建在服务器172.28.11.4这台服务器上,正常情况下,我在宿舍或WebVPN访问时,数据会带着ip地址例如172.31.0.100告知服务器返回数据的位置,服务器接收到数据并进行处理后,准备返回数据,这时发现要返回的地址不在路由表上,于是就向机柜交换机发送数据,让机柜交换机查找目标地址然后一直向上级交换机发送数据,直到找到路由表里有这个地址的交换机,然后向下转发数据,这样我们就可以收到服务器的回复数据。
然而,如果我们在机房电脑172.17.1.2访问服务器,服务器接收到数据并进行处理后,准备返回数据,这时发现要返回的地址在路由表上,这个路由表是docker写上去的,和机房的电脑的网段正好相一致,于是他就会直接通过路由表所写的信息,将数据转发给对应ip的docker容器(即使这个容器不存在),这样,我们就收不到服务器所返回的数据,就会造成无法访问,ping也ping不通。
解决方法也很简单,就是重新分配docker的网段。
0x03 查找容器ip地址
首先列出所有容器
1 | docker ps -a |
接着,针对容器,进行查询。例如,我们想查找容器 oj-backend (6ada6469fe6d) 的ip地址,输入
1 | docker inspect 6ada6469fe6d |
IPAddress后面跟的就是容器的ip地址,Gateway后面跟的就是虚拟网关。
我们找到所有我们需要重新分配ip的容器,记住容器名称,例如 oj-backend 、 oj-judge 、 oj-redis 。
0x04 查找网桥
首先列出所有docker网桥
1 | docker network ls |
接着,针对网桥id,查看详细信息。例如,针对 docker_default (4969db1ebd36) 查找输入以下指令
1 | docker network inspect 5bc11281f0ae |
Subnet后面跟的就是网桥的网段,Gateway后面跟的就是虚拟网关。
我们找到我们需要重新分配网段的网桥,记住网桥名称,例如 docker_default 。
0x05 停止容器
进入文件所在的文件夹,输入以下指令停止服务。
1 | docker-compose stop |
0x06 修改容器设置
我们找到 docker-compose.yml
文件,打开编辑,在下面找是否有类似以下内容的部分
1 | networks: |
如果有,则修改网段,如果没有,则复制上面的内容在文件下方粘贴。
0x07 删除原网桥
我们使用刚刚记住的网桥名称,删除它
1 | docker network inspect docker_default |
0x08 重启docker服务
使用指令
1 | service docker restart |
重新启动服务
0x09 重建网桥
进入文件所在的文件夹,输入以下指令就可以重建网桥。
1 | docker-compose up -d |
此时会报错,这是因为我们虽然新建了网桥,但是容器并未连接到新网桥,我们不用管。此时我们列出所有docker网桥,会发现网桥已经重建好了。
1 | docker network ls |
0x0a 让容器连接新网桥
使用我们记住的网桥名称和网络名称,使用指令让容器连接到新网桥。
1 | docker network connect docker_default oj-backend |
0x0b 启动容器
进入文件所在的文件夹,输入以下指令启动的时候,应该就不会报错了,机房也就可以正常访问了。
1 | docker-compose up -d |
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏