docker网络简介
docker的网络部分是非常重要的一个分支。 docker安装好后宿主机增加多了两个虚拟网卡接口(docker0,br-1d3799005cb5),用ip addr命令看到如下,docker0网段172.17.0.0,br-1d3799005cb5网段172.18.0.0
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 ...... 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:66:d2:4f brd ff:ff:ff:ff:ff:ff inet 192.168.228.44/24 brd 192.168.228.255 scope global noprefixroute ens33 ...... 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:14:95:53:83 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever ...... 5: br-1d3799005cb5: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:47:f9:d3:b2 brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 brd 172.18.255.255 scope global br-1d3799005cb5 ......
对docker-engine默认会有4个网桥(或者说是交换机),用docker network ls命令查看如下,名为bridge的网桥对应到docker0虚拟网卡172.17.0.0,名为docker-default的对应br-1d3799005cb5虚拟网卡接口172.18.0.0。
docker network ls NETWORK ID NAME DRIVER SCOPE 704ee94879e3 bridge bridge local 1d3799005cb5 docker_default bridge local e6cc2af3037d host host local 3144be175a0e none null local
有没注意到DRIVER,这是网络模式,docker里面预定义了4种模式,分别如下
- bridge
注意引用‘bridge’的词地方不少,都是不同代表的,就像上面取名NAME是bridge,DRIVER也有个bridge,不要混在一起哦;这里是后者,代表是桥接,和vmare里nat一样,与宿主机物理网络是隔离的,如果要访问外面的internet,要经过NAT地址转换;容器没显式指定--net=?时默认采用bridge模式。两个不同bridge间是隔开的,譬如上面的bridge和docker_default,在容器内部互相ping不通,即容器ip为172.18.0.x ping 172.17.0.x会失败。 - host
共享宿主机网络 - container
使用某个已存在的容器的网络namespace,注意是和配置的目标容器共享网络资源,端口不要冲突。 - null
无网络,一般不需要通过网络通信的容器可以使用这种,节省开销。
自定义网桥
在一个宿主机上有多组容器,组与组之间要进行隔离或者某些加入多个组,这情况下需要自行通过docker network create命令去创建自定义网桥,创建成功后docker network ls会看到多出一项接口(非host/null模式时宿主机也会多块虚拟网卡); 创建时要选择模式--driver=参数指定,这个参数除了上面说的4个模式外,还有bridge,overlay,主要针对跨宿主机间的容器通信。用docker-compose启动的容器默认会创建一个名为dir_default的网桥(yml里没指定网络),而直接用docker run启动的容器默认会加入docker0网桥。
docker-compose配置(参考)
下面示例定义了3个命名网络,如果当前目录是dir,则启动后产生NAME为dir_front,dir_back这2个网桥(虚拟网卡接口),default配置是当容器配置(services)当中无显式指出networks时,将使用的网络,这里是配置成使用外部网桥,名字是cppcloud_default,可以在docker network ls查看。 容器间的访问配置取别名,同一个docker-compose.yml配置的用links,不同要用external_links。
networks:
front:
drive: bridge
default:
external:
name: cppcloud_default
back:
drive: bridge
部署过程问题
-
宿主机网络出问题
现象:宿主机不能访问外部网络,ping 域名/ip都失败,network unreachable;
排查:这是由于docker某些操作导致宿主机路由表被破坏了,ip route看到默认网关没有了,那肯定访问外网会有问题;至于什么操作破外了,不得知了;
解决:手动添加一条默认网关,ip route add default via <gw_ip> dev ens33;// 你要事先查出宿主机的出口网关是什么。 -
运行脚本出错
现象:出现OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "no such file or directory": unknown;
解决:虽然提示信息不明显,经网上找答案,这是执行到某shell脚本是存在win换行符\r,应sed -i'' "s//r//" file; -
dockerfile RUN合并问题
现象:dockerfile里用一个RUN命令执行多个命令正常,拆开成多个RUN时失败;
排查:docker build时某些RUN命令生成层时需要会启动一些临时容器去执行并生成层(layer),这也是为什么经常看到有none名字的image;如果RUN里面开启了一些tcp服务或某些进程,那么RUN结束后临时容器会关闭,后面的RUN命令将新开启新的临时容器,所以后RUN操作就不能依赖前RUN操作启动的服务了。 -
volume映射问题
现象:数据库遇到Error: could not exec /usr/lib/postgresql/9.3/bin/pg_ctl;
排查:因为做volume映射时一般是root所有者,postgresql的db目录下的文件默认是postgres。
解决:在容器里面执行chown -R postgres:postgres dir;
引申出docker volume文件/目录映射时,如果容器里面需要用非root用户访问时需注意;volume映射是以宿主机为主,如果想找容器里已存在的目录映射出去到一个宿主机目录,不能volume做,而应该先使用docker cp命令,再映射; window上作volume有问题,特别是非C盘下的映射,需要配置共享权限比较麻烦,建议还是在linux下做。 -
dockerfile COPY/ADD
dockerfile命令COPY/ADD命令的第一个参数(即原path)不能使用相对路径../xx;