Docker--认识Docker网络 Network NamespaceNetwork Namespace 是Linux用于实现网络虚拟化的重要功能他能创建多个隔离的网络空间每个独立网络空间内的防火墙、网卡、路由表、邻居表、协议栈都是独立的。不管是虚拟机还是容器当运行在独立的命名空间时就像是一台独立的主机一样。现在的需求是创建2个Network Namespace然后连通他们。创建2个命名空间创建网络接口veth pair如果要让两个命名空间连通需要用到虚拟设备接口技术veth pair。该技术需要一对网络接口分别置于两个命名空间中。下面命令用来创建一对网络接口veth-ns1 和 veth-ns2ip link add veth-ns1 type veth peer name veth-ns2此时通过ip link 查看当前网络地址情况看到新增了两个胡同的veth pair,他们都有MAC地址但是状态都是DOWN都没有IP。命名空间添加veth接口通过ip link set 命令将刚才两个接口分配给两个命名空间ip link set veth-ns1 netns ns1 ip link set veth-ns2 netns ns2此时分别在两个命名空间中执行 ip link 命令可以看到他们都新增了网络接口为veth 接口分配IP通过ip netns exec命令为每个命名空间添加IPip netns exec ns1 ip addr add 192.168.1.1/24 dev veth-ns1 ip netns exec ns2 ip addr add 192.168.1.2/24 dev veth-ns2此时通过在ns1与ns2中运行ip a命令可以看到接口都有ip了启动veth接口通过ip link set dev [接口] up 来启动指定的网络接口。ip netns exec ns1 ip link set dev veth-ns1 up ip netns exec ns2 ip link set dev veth-ns2 up相互pingCNMdocker网络架构由三部分组成CNM、Libnetwork 与Driver。CNM Container Network Model容器网络模型是一种网络连接的解决方案是一种设计规范、设计标准其规定了Docker网络的基础组成要素。CNM中定义了三个基本要素沙盒Sandbox终端Endpoint 与网络Network。沙盒一个独立的网络栈包括以太网接口、端口号、路由表、DNS配置等。LInux Network Namespace 是沙盒的标准实现。终端虚拟网络接口负责创建连接即将沙盒连接到网络上一个终端只能接入一个网络。网络802.1d网桥的软件实现是需要交互的终端的集合。LibnetworkLibnetwork 是开源的、go语言编写、跨平台的CNM的标准实现。Libnetwork 除了实现CNM的三个组件还实现了本地服务发现、容器负载均衡、网络控制层与管理层功能。Driver不同的网络类型对应不同的底层Driver这些Driver负责在主机上真正实现需要的网络功能例如创建veth pair 设备等。无论哪种网络类型。工作方式都是类似的。调用Docker 引擎的API 发出请求Libnetwork 做出框架性处理将请求转发给对应的Driver。通过docker network ls 命令可以查看当前主机所连接的网络及网络类型bridge 网络bridge 网络 也称单机桥接网络是Docker 默认的网络模式。该模式只能存在单个Docker主机上只能连接所在Docker主机上的容器。docker0网桥bridge网络 模式中有个默认的虚拟网桥docker0通过ip a 或者ifconfig 命令可以查看docker0网桥的工作原理在Linux主机上Docker 的bridge 网络在创建时会创建一个默认网桥docker0。容器和网桥通过veth pair 技术连接网桥与外网通过网络地址转换NAT技术连接就是将通信的数据包中的内网地址转换为外网地址。查看网络连接情况通过 docker network inspect 命令查看当前bridge网络的连接情况。Containers 中可以看到bb1 和bb2 两个容器这两个容器和宿主机就是三个完全独立的Network Namespace。查看宿主机接口发现除了回环地址lo本地网卡ens33网桥docker0外还有两个veth网络接口。这两个veth就是由Libnetwork 生成的veth pair中宿主机的EndPoint。vethxxxif4:表示第5个接口用来连接外部的第四个接口vethxxxif6:表示第7个接口用来连接外部的第六个接口查看容器接口可以看到两个容器都包含eth0接口。bb1的接口4即ethif5 来连接宿主机的第5个接口bb2的接口6即ethif7 来连接宿主机的第7个接口查看网桥连接先安装网桥的工具包bridge-utilsyum -y install bridge-utils可以看到网桥有两个接口。创建网络通过docker network create 命令可以创建指定名称和类型的网络docker network create -d bridge bridge2-d : 指定网络类型。bridge2是网络名称。通过docker network ls可以看到刚才创建的网络。创建容器指定网络创建一个新的BusyBox容器bb3 然后连接在新建的bridge2 网络上。docker run -d --name bb3 --network bridge2 /bin/sh -c while true; do sleep 3600; done通过--network 指定要连接到的网络如果不指定就连接默认的。查看新建的网络详情可以看到bb3容器已经连上了。此时查看宿主机网络接口和bb3容器网络接口发现他们的接口都对应上了。容器连接到指定网络现将容器bb2连接到bridge2 上。可以使用docker network connect 命令docker network connect bridge2 bb2此时bb2容器连接在两个网络上具有两个IP此时容器bb2 和bb3 可以ping 通但是bb3 和bb2的另一个网段是ping不通的。容器除了可以直接ping IP外还可以直接ping 容器名称docker exec bb3 ping bb2创建定向连接容器自定义的bridge网络可以通过容器名互相ping。但是默认的bridge不行。如果想在默认的bridge网络上通过容器名称进行连接则在创建容器时通过--link 指定。docker run -d --name bb4 --link bb1 busybox /bin/sh -c while true; do sleep 3600; done此时bb4 可以用容器名称ping bb1docker exec bb4 ping bb1注意bb1 无法通过容器名称ping bb4 因为--link 是一种定向连接带有指向性和方向性。创建共享网络命名空间容器创建容器时可以指定其与已经存在的容器共享 Network Namespace 。但要求已存在容器必须采用bridge模式。docker run -d --name bb1-1 --network container:bb1 busybox /bin/sh -c while true; do sleep 3600; done此时这两个容器的网络接口完全相同。none网络none网络即没有网络。容器仍是一个独立的Network Namespace 但是没有网络接口没有IP。创建none网络容器在docker run 命令中通过--network none 指定没有网络docker run -d --name bb5 --network none busybox /bin/sh -c while true; do sleep 3600; done # 查看容器详情发现没有IP没有网关没有MAC地址 docker inspect bb5 # 查看网络接口发现只有一个回环地址lo没有其他接口 docker exec bb5 ip ahost网络host网络与宿主机host共用一个Network Namespace。该网络类型的容器没有独立的网络空间没有独立IP。全部与host共用。创建host网络容器通过--network host指定为host网络。docker run -d --name bb6 --network host busybox /bin/sh -c while true; do sleep 3600; done # 查看host网络详情发现bb6 连接在该网络上但是没有IP、MAC并且该网络没有网关Gateway。 # 因为该网络模式相当于没有网络容器与宿主机共用Network Namespace不需要网络连接。 docker network inspect host关于端口映射由于容器和宿主机共用一个Network Namespace。所以无论IP还是Port 容器和宿主机都是相同的。所以容器中的Port 不存在映射问题host中的Port 和容器中的Port相同。# 运行tomcat docker run --name mytom --network host -dp 8081:8080 tomcat:8.5.32上面虽指定了端口映射但是网络是host类型所以端口映射不起作用。此时仍需要通过8080端口访问。