docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。docker安装后会自动创建3种网络:bridge、host、none
Docker在启动时会开启一个Linux bridge(虚拟网桥设备)docker0,默认的地址为172.17.0.1/16,容器启动后都会被桥接到docker0上,并自动分配到一个ip地址.
1.docker网络中的bridge网络模式bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容器通过宿主机的NAT规则后可以访问外网。
容器的ip地址以单调递增的方式进行分配,如果容器禁用,其ip地址会被释放,可以分配给其他容器使用。
[root@server1 harbor]# docker-compose down [root@server1 harbor]# docker network ls ##查看docker的网络有三种 NETWORK ID NAME DRIVER SCOPE f7ee76587a55 bridge bridge local 7a440d19230c host host local 72bd4b55c59a none null local [root@server1 harbor]# ip addr 5: docker0: inet 172.17.0.1/16 [root@server1 harbor]# docker run -d --name demo nginx ###后台运行一个demo为nginx [root@server1 harbor]# yum install -y bridge-utils [root@server1 harbor]# brctl show [root@server1 harbor]# docker inspect demo------>"IPAddress": "172.17.0.2", 17.0.1是宿主机上docker0的ip [root@server1 harbor]# iptables -t nat -L
172.17网段开启了地址伪装:MASQUERADE
Bridge桥接模式的缺陷:
该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
2. docker网络中的host网络模式
host网络模式需要在容器创建时指定–network=hosthost 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机的 IP地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
创建host网络模式的一个容器并查看ip,会发现此时的ip与宿主机(docker0)中的ip一样
[root@server1 ~]# docker run -it --rm --network host busybox / # ip addr [root@server1 ~]# ip addr [root@server1 ~]# docker ps [root@server1 ~]# docker rm -f demo3. docker网络中的none网络模式
none模式是指禁用网络功能,只有lo接口,在容器创建时使用–network=none指定。
创建一个none网络模式的容器vm3并查看ip,会发现此时只有lo接口
[root@server1 ~]# docker run -it --rm --network none busybox二、docker自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:
bridge overlay macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
[root@server1 ~]# docker run -it --rm --name demo busybox / # ping demo ping: bad address 'demo' / # [root@server1 ~]# docker run -d --name demo1 nginx ##开启demo1
[root@server1 ~]# docker inspect demo1 ###查看demo1的ip
[root@server1 ~]# docker stop demo1 demo1 [root@server1 ~]# docker run -d --name demo2 nginx
[root@server1 ~]# docker inspect demo2 ###关闭demo1,开启demo2,查看demo2的ip:占用了之前demo1的ip
再开启demo1,查看ip为0.3
[root@server1 ~]# docker start demo1 demo1 [root@server1 ~]# docker inspect demo1
不同容器之间进行通信只能ping其ip,不能ping名称
1.自定义网络创建(1)创建自定义网桥
[root@server1 ~]# docker network create mynet1 [root@server1 ~]# docker network ls [root@server1 ~]# docker network create --subnet 172.10.0.0/24 --gateway 172.10.0.1 mynet2 ##还可以自定义网段
(2)使用自定义网络启动容器
[root@server1 ~]# docker run -d --name demo1 --network mynet1 nginx ###后台启动demo1 [root@server1 ~]# docker run -it --rm --network mynet1 busybox ###交互式启动buxybox / # ping demo1
测试可以ping通demo1
2.不同网桥的容器如何通信(1)使用带参数的方法重新创建新的自定义网络,使用新的自定义网络运行demo容器
–subnet: 子网掩码
镜像信任功能能够保证镜像的安全,只有打了信任标签的镜像才能被拉取–gateway: 网关
(2)创建一个新的自定义网络mynet2
demo2用mynet2后台启动
[root@server1 ~]# docker network create --subnet 172.10.0.0/24 --gateway 172.10.0.1 mynet2 [root@server1 ~]# docker run -d --name demo2 --network mynet2 --ip 172.10.0.10 nginx
此时demo1为mynet1的18网段,demo2为mynet2的10网段,是不能通信的
(3)使用docker network connect 命令为 demo3添加一块mynet2 的网卡。
三、容器通信 1.使用容器名称通信[root@server1 ~]# docker run -it --name demo3 --network mynet1 busybox / # ping demo1 ###可通 [root@server1 ~]# docker start demo3 [root@server1 ~]# docker network connect mynet2 demo3 ###为demo3添加一块mynet2的网卡 [root@server1 ~]# docker attach demo3 / # ip addr / # ping demo2 ###demo3能ping通demo2
Container 网络模式是 Docker 中一种较为特别的网络的模式。
Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
在容器创建时使用–network=container:vm指定(vm指定的是运行的容器名)
[root@server1 ~]# docker run -d --name demo nginx ##后台启动nginx [root@server1 ~]# docker inspect demo ##查看ip [root@server1 ~]# docker run -it --network container:demo busybox ###container启动buxybox,用demo的网络 / # ping demo ping: bad address 'demo' / # ping localhost PING localhost (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.107 ms
ping容器名是不通的,因为创建容器时使用的默认网桥,没有地址解析,只有私有网络才可以ping容器名
--link
--link 可以用来链接2个容器。
--link的格式:
--Jink 创建demo:webserver容器并进行连接,可以ping通 当容器的ip改变时link会自动改变解析,但同一个容器的env变量不会变 停掉demo容器,用ngix镜像拉起容器demo1,查看ip demo1的ip为刚刚demo的ip 再次拉起demo,ip发生改变 再次用link拉起demo:webserver,依然可以ping通demo,查看域名解析文件,demo对应的ip变为172.17.0.3,但env变量不变 端口映射-p选项指定映射端口
DNAT:外网访问宿主机ip时,通过端口映射自动定向到demo的172.17.0.2 测试: DNAT:双冗余机制,docker-proxy和iptable只要有一个在就可以进行通信 删除iptable中的ipv4的80端口映射,依然可以访问 [root@server1 ~]# iptables -t nat -D DOCKER 4 测试:curl 172.25.70.1 再删除docker-proxy的进程,外部无法访问,此时iptable和proxy都是关闭的,但此时的demo依然是ok的,宿主机可自由访问 [root@server1 ~]# netstat -antlp [root@server1 ~]# kill -9 2178 [root@server1 ~]# docker ps stop之后再start容器,iptable和proxy会继续映射80端口,此时停止docker-prosy,iptable依然存在,外网依然可以访问 测试: 跨主机网络解决方案: docker原生的overlay和macvlan 第三方的flannel、weave、calico众多网络方案是如何与docker集成在一起的 libnetwork docker容器网络库 CNM (Container Network Model)这个模型对容器网络进行了抽象CNM分三类组件 Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace) Endpoint:作用是将sandbox接入network (veth pair) Linux kernel提供的一种网卡虚拟化技术。无需Linux bridge,直接使用物理接口,性能极好。
清除之前的网络设置和容器,保证两台主机的容器和网络设置一致 在两台docker主机上打开网卡混杂模式: server1: 创建macvlan1网络 使用macvlan1网络运行busybox镜像容器: server2: 导入busybox 创建macvlan1网络,并使用macvlan1网络运行busybox镜像容器 server1和server2之间可以相互ping通 macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094。
server1和server2新加一块网卡eth1 server1: 编写eth1的配置文件,启用eth1网卡并开启混杂模式 容器的接口直接与主机网卡连接,无需NAT或端口影射。 macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络 利用macvlan创建mynet1网络:eth1.1为eth1的子接口,这样虚拟网卡的ip不会冲突,也可实现批量分配,如 server2也做相同的操作 再server1和server2上,使用mynet1网络运行busybox镜像容器:可以ping通 macvlan网络间的隔离和连通 macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。.可以在三层上通过网关将macvlan网络连通起来。docker本身不做任何限制,像传统vlan网络那样管理即可。
在三层上通过网关将macvlan网络连接起来 [root@server1 ~]# docker network connect macvlan1 demo2 在三层上通过网关让demo2和amcvlan1连接起来 ping通: [root@server1 ~]# docker run -it --rm --link demo:webserver busybox ###link会自动解析
/ # ping demo
/ # cat /etc/hosts
172.17.0.2 webserver 37e3a69b5387 demo ###demo的解析
172.17.0.3 1626e30f3ccb
/ # env ###查看变量
[root@server1 ~]# docker stop demo
[root@server1 ~]# docker run -d --name demo1 nginx
[root@server1 ~]# docker inspect demo1
3.外网访问容器
[root@server1 ~]# docker run -d --name demo -p 80:80 nginx ##端口映射
[root@server1 ~]# docker port demo
[root@server1 ~]# iptables -t nat -nL
[root@server1 ~]# docker stop demo
[root@server1 ~]# docker start demo
Network:包含一组endpoint,同一network的endpoint可以通信。
macvlan网络方案实现
[root@server1 ~]# docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth0 macvlan1
[root@server1 ~]# docker run -it --rm --network macvlan1 --ip 172.20.0.10 busybox
/ # ip addr
[root@server2 ~]# docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth0 macvlan1
[root@server2 ~]# docker run -it --rm --network macvlan1 --ip 172.20.0.11 busybox
/ # ip addr
2.跨主机不同网段容器通信
vlan可以将物理二层网络或分为4096个逻辑网络,彼此隔离[root@server1 network-scripts]# docker network create -d macvlan --subnet 172.30.0.0/24 --gateway 172.30.0.1 -o parent=eth1.1 mynet1
批量分配:
[root@server1 network-scripts]# docker network create -d macvlan --subnet 172.40.0.0/24 --gateway 172.40.0.1 -o parent=eth1.2 mynet2
[root@server1 ~]# docker run -it --rm --network mynet1 --ip 172.30.0.100 busybox
[root@server2 ~]# docker run -it --rm --network mynet1 --ip 172.30.0.101 busybox
[root@server1 ~]# docker run -it --rm --network macvlan1 --name demo1 --ip 172.20.0.100 busybox (demo1:ctrl+p+q退出后台运行)
[root@server1 ~]# docker run -it --rm --network mynet1 --name demo2 --ip 172.30.0.100 busybox
/ # ping demo1 ###不通,不同网段



