docker 的网络类型
1: bridge 2: host 3: none 4: container
docker 四种网络类型的不同之处
从 net namespace 的角度来看, host 类型为 容器共享宿主机的 net namespace container 类型,则是两个容器共享一个 net namespace bridge类型 一个容器享有一个 net namespace none 类型,容器也会享有一个 net namespace ,但是容器无法连接外网。
bridge
docker 容器 网络类型 为bridge时 所具有的能力
在宿主机能访问外网的前提下 1: 容器 和外网进行通信 2: 外网能访问容器 (容器运行时 使用端口映射)
bridge 类型的背后实现
所启动的容器 网络类型是 bridge 类型时,容器启动时被分配一个网桥子网内的ip地址, 创建一对 veth pair 设备,一个作为容器的eth0网卡,一个被连接到网桥上。 iptables 会根据容器的启动参数,相应增加规则 概括地说:ip_forward + iptables + bridge + veth pair 使 容器能和外网互通。
自定义网络
自定义一个桥接类型的网络的实质是什么?
在宿主机上创建一个新的网桥,并为网桥分配一个子网地址, 在iptables nat 表 POSTROUTING链之中配置 snat 转换规则。
创建一个网络的使用例子
docker network create --driver bridge 网络名
将一个容器加入到某个网络之中
docker run 的 --network 参数,取值设置为网络名
ip forward
查看当前的宿主机 ip forward 功能 是否开启
cat /proc/sys/net/ipv4/ip_forward
如果输出值为1,那么表示开启,如果输出值为0,那么表示ip_forward并没有被开启。
注意:如果ip forward 功能并未开启,那么网络类型为 bridge 的 容器,就无法和外网进行通信了。
docker-proxy 介绍
作用
容器启动时,配置了端口映射参数,会启动一个docker-proxy 进程,来监听宿主机上容器映射的端口。有些情况下,访问容器的请求,并没有匹配到DNAT规则,那么由docker-proxy来处理,规避 docker0 并没有开启发夹模式而可能导致的问题。
docker 是否 默认开启 docker-proxy, 如何验证?
dockerd --help | grep proxy
docker 是否可以关闭 docker-proxy 模式?
可以的。 /etc/docker/daemon.json 之中配置相应参数,重启docker 即可。 参数名为: dockerd --help | grep proxy 来获得 注意:如果关闭 docker-proxy 机制,那么docker0需要开启发夹模式,否则有些访问可能出现问题,例如(容器访问 宿主机ip+映射端口)
docker-proxy 机制带来的问题
搜索结果: 每启动一个 执行端口映射的容器,都会在机器上启动一个 docker-proxy 进程。 进程会占据一些内存,如果docker-proxy进程数过多,可能会占用大量的内存。 但是也有其他人实际测试:大量的docker-proxy进程,并不会占据大量的内存。
docker 容器内 向外网发送数据,数据的流转图
参与组件 iptables 网卡设备 行为: 在宿主机上的一个容器内 执行 curl 110.242.68.4, 对应的数据包的流转图示 验证方式 iptables -t 表明 -I 链名 -j LOG --log-prefix="相应的输出信息" dmesg | grep "相应的输出信息" 自己在 iptables 某个表的某个链之中增加相应的 打印规则,来判断数据的流向
注意:当容器使用端口映射的方式,向外暴露端口,外部主机访问本机容器时,数据流转和上面的一致。
在容器启动时 建立端口映射的前提下,在容器内 访问 宿主机ip+映射端口,数据流转图
注意:这里的数据包并没有被docker 设置的 iptables DNAT规则所匹配,使数据包的流转走向了INPUT链,规避了 docker0网桥没有开启发夹模式 所可能导致的问题,数据包的处理由docker-proxy进程来执行。
docker 容器 端口映射 的 背后原理
启动容器时,配置端口映射,使外网能够访问此容器。背后的支撑是 iptables 的DNAT 以及 docker-proxy。
docker 网络调试 小技巧
如何进入docker容器进程的网络空间
nsenter -n -t 容器进程id
注意: 这样可以解决容器内没有网络软件安装包的问题。
当容器无法连通外网的时候,如何调试?
1:首先排查 容器 与 docker0 之间是否连通 2:然后排查 docker0 与 eth0 之间的iptables 规则。
操作
1: 查看docker daemon 设置的默认网络类型
自己未找到 寻找 docker daemon 设置的默认网络类型的方式,
据搜索得知 docker daemon 设置的容器的默认网络类型为 bridge
2: 查看 docker容器 的网络类型
docker inspect -f {{.NetworkSettings.Networks}} 容器id