问题

最近把服务器从华为云迁移到阿里云,因为原先有两个应用跑在docker上,所以选服务器镜像的时候直接选择了自带docker的轻量应用服务器,服务器上手之后准备直接从dockerhub pull之前上传的镜像,因为app里没有需要保存的数据所以就直接点。但是这时候坑出现了,容器跑起来了但是外网怎么也访问不了。

排查

首先想的是不是防火墙没设置对,但是在firewalld里开放了需要的端口,也在云安全组里放行了,但是怎么都访问不了,奇怪的是宿主机上跑的frps却可以正常访问,说明不是安全组或者防火墙规则的问题,因为端口我已经再三确认的确没问题了。

于是想到是否是docker网络的问题?

首先我用ip a查看docker 0的网络

3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:db:12:5c:6c brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.20.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:dbff:fe12:5c6c/64 scope link 
       valid_lft forever preferred_lft forever

然后尝试自己新建一个网络,然后把容器指定到使用这个网络

docker network create 01_network

docker run -dit --name my-apache-app --network=01_network -p 8888:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4

没想到果然尝试访问成功!

那么基本可以确定,是docker默认的这个网桥搞的鬼。

修改

确认好问题后,咱们就尝试去修复下,在bing上搜索如何修改docker默认的网络,发现可以在/etc/docker/daemon.json中修改默认网桥网关的地址。

先用这个命令停掉默认的网络

ifconfig docker0 down

也就是下面这个默认的e437c637c047 bridge

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ed437f64ada1        01_network          bridge              local
e437c637c047        bridge              bridge              local
281118b78fa3        host                host                local
55f475a6cc84        none                null                local

/etc/docker/daemon.json 这个文件也就是我们配置镜像加速器时候打开的那个文件,要注意如果没有创建需要先创建文件,然后在文件中加入这个键值对(注意如果配置了加速器只需要加入括号内键值对,不要少了逗号):

这个网络看你自己ip段依情况设置

然后重启docker服务:systemctl restart docker

再次查看网络:

3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:db:12:5c:6c brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.1/16 brd 172.20.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:dbff:fe12:5c6c/64 scope link 
       valid_lft forever preferred_lft forever

这时候docker 0默认网桥的ip已被修改成功

大功告成把网络起起来

ifconfig docker0 up

分析

猜测故障原因是因为我是使用预装docker的服务器镜像,然后我发现没装firewalld,用yum安装后可能覆盖了原先的防火墙规则,不过奇怪的是iptables里面也并没有预先设置规则。