目录
一、Docker原生网络
1、bridge网络
2、host 模型
3、none模型
二、Docker自定义网络
1、bridge
1)创建网桥
2)创建自定义网桥,自定义网段
2、overlay和Macvlan
三、Docker容器通信
1.Joined
2. link模式
3.外网访问容器
四、跨主机容器网络
macvlan网络方案实现
vlan子接口实现
docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。
docker安装后会自动创建3种网络:bridge、host、none
docker network ls #使用以下命令查看
cd harbor/
docker-compose down ##停止容器
docker network ls ##docker的原生网络有三个
ip addr #docker安装后有一个docker0的桥接口
关闭docker容器后发现只有三个原生网络。
docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口。这样主机上的所有容器就通过交换机连在了一个二层网络中。
docker run -d --name demo nginx ##开启新容器
docker ps
yum install -y bridge-utils #下载该插件用于查看桥接
brctl show ##可以看到容器网络桥接到宿主机docker0上
docker inspect demo ##查看容器的信息,看到容器的网关为172.17.0.1
docker inspect demo 查看容器的信息,看到容器的网关为172.17.0.1
172.17.0.1就是docker0
iptables -t nat -nL #可以看到有一个地址伪装
容器的地址是动态分配的,分配一个和网桥 docker0
在同网段的IP地址给容器,并设置 docker0 的 IP 地址为容器的默认网关。先启动就先分的地址,容器关闭就会被释放。供其他的容器连接。
Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.0.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。
————————————————
版权声明:本文为CSDN博主「@Limerence」的原创文章,遵循CC 4.0 BY-SA版权协议,
原文链接:https://blog.csdn.net/meltsnow/article/details/94490994
host网络模式需要在容器创建时指定 --network=host
docker run -d --name demo2 --network host nginx ##-d 打入后台
docker ps
brctl show #查看桥接信息
docker inspect demo2 #查看详细信息
查看demo2的详细信息,发现没有网关和 ip相关信息。
docker run -it --name demo2 --network host busybox ##运行busybox打开终端
进来以后查看ip addr 与宿主机完全一致
此时直接访问宿主机的ip地址就能访问到该容器。
测试:将原来的容器都删除,然后重新运行一个demo容器。
docker ps -a
docker rm -f demo
docker rm -f demo2
docker run -d --name demo --network host nginx ##运行demo
ip addr ##没有新建网络
brctl show
此时没有生成新的网络,新的桥接。
curl 172.25.0.1 #在server2访问server1的ip地址
在server1上查看端口80,有nginx,但不是宿主机本身的,然后将容器停掉便无法访问。从而证明是容器的。
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
none模式是指禁用网络功能,只有lo接口,在容器创建时使用 --network=none指定。
docker run --rm -it --network none busybox #可以看到只有lo接口
该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,在以下两种情况下是有用的:容器并不需要网络比如重要的数据等。或者是单独把网络部分独立出来全手工的方式创建网络栈。
没创建一个容器,容器就会有自己的id,相当于一个进程。会有6个namespace。也就是6种命名空间。相对的作为一台主机存在。
docker ps
docker run -d --name demo nginx
docker ps
docker inspect demo | grep Pid
cd /proc/19943/ #进入到进程里面
ls
cd ns
• 自定义网络模式, docker 提供了三种自定义网络驱动:• bridge• overlay• macvlanbridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。
• 建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
你可以根据需要创建任意数量的网络,并且可以在任何给定时间将容器连接到这些网络中的零个或多个网络。此外,您可以连接并断开网络中的运行容器,而无需重新启动容器。当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。
————————————————
版权声明:本文为CSDN博主「@Limerence」的原创文章,遵循CC 4.0 BY-SA版权协议,
原文链接:https://blog.csdn.net/meltsnow/article/details/94490994
docker rm -f demo #删除原来创建的容器,只剩下三个原生网络
docker network create --help #网络创建的帮助
docker network create mynet1 #创建网络mynet1
docker network ls ##也是属于桥接模式
都是桥接,有什么不同呢?
测试:建立两个容器在默认桥接bridge下,然后ping。
docker run -d --name demo1 nginx
docker run -it --rm busybox #交互式的,ping demo1用于查看现象
发现可以ping通demo1的ip但是无法ping通“demo1”。
连接自定义网络mynet1时
docker rm -f demo1 #重新建立demo1
docker run -d --name demo1 --network mynet1 nginx ##运行时指定网络
brctl show
docker network inspect mynet1 ##网络ip为172.23.0.2,网关为172.23.0.1
ip addr
发现可以ping通域名“demo1”
当停掉demo1重新建立demo2,再开启demo1时。访问demo1会自动变化ip。 之前的ip释放后被新建立的demo2 使用。现在成为172.23.0.2
demo2变成了172.23.0.2
自定义网络bridge,自带dns解析,因此可以访问域名。由于docker容器是会发生故障的,而容器的ip是动态分配的,因此自定义网络会更加有优势。
docker run -d --name demo3 --network mynet1 --ip 172.24.0.10 nginx #指定ip,不再递增获取自己指定
发现mynet1不能手动指定ip
使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持,同一网桥上的容器是可以互通的。
我们删除之前的创建的容器,和网络,重新建立。
docker ps -a
docker rm -f demo1
docker rm -f demo2
docker rm -f demo3
docker network rm mynet1
在创建时指定参数:--subnet 、--gateway
docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 mynet1 #创建网桥指定网段,不能和本机现有网段冲突
docker network inspect mynet1 ##查看mynet1详情
docker run -d --name demo1 --network mynet1 --ip 172.20.0.10 nginx ##指定ip运行容器
curl 172.20.0.10 可以访问到
再创建一个网段的网络。
docker network create --subnet 172.30.0.0/24 --gateway 172.30.0.1 mynet2
docker network ls
docker network inspect mynet2
docker run -d --name demo2 --network mynet2 --ip 172.30.0.10 nginx
brctl show
mynet1和mynet2默认情况下不通,防火墙有控制,不同容器间做了网络隔离。
iptables -t nat -nL
docker run -it --rm --network mynet1 busybox
docker run -it --rm --network mynet2 busybox
桥接到不同网桥上的容器,彼此是不通信的,docker在设计上就是要隔离不同network的
docker ps
docker network connect mynet1 ID/NAMES ##把busybox接入到mynet1中
再次ping两个网段都通了。
在docker1.7代码进行了重构,单独把网络部分独立出来编写,所以在docker1.8新加入的一个overlay网络模式。Docker对于网络访问的控制也是在逐渐完善的。
Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点。Linux实现非常轻量级,因为与传统的Linux Bridge隔离相比,它们只是简单地与一个Linux以太网接口或子接口相关联,以实现网络之间的分离和与物理网络的连接。
Macvlan提供了许多独特的功能,并有充足的空间进一步创新与各种模式。这些方法的两个高级优点是绕过Linux网桥的正面性能以及移动部件少的简单性。删除传统上驻留在Docker主机NIC和容器接口之间的网桥留下了一个非常简单的设置,包括容器接口,直接连接到Docker主机接口。由于在这些情况下没有端口映射,因此可以轻松访问外部服务。
————————————————
版权声明:本文为CSDN博主「@Limerence」的原创文章,遵循CC 4.0 BY-SA版权协议,
原文链接:https://blog.csdn.net/meltsnow/article/details/94490994
• 容器之间除了使用 ip 通信外,还可以使用容器名称通信。• docker 1.10 开始,内嵌了一个 DNS server 。• dns 解析功能必须在自定义网络中使用。• 启动容器时使用 --name 参数指定容器名称 。
• Joined容器 一种较为特别的网络模式。• 在容器创建时使用 --network=container:vm1 指定。( vm1 指定的是运行的容器名)
docker ps -a
docker container prune ##删除所有已经停止的容器
docker run -d --name demo nginx ##开启新的容器
docker network ls
docker inspect demo
docker run --rm -it --network container:demo busybox ##新建的容器和demo使用一个网络栈
发现新打开的容器和demo使用同一网络栈。
•处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
link模式通过/etc/hosts文件来做解析
--link 可以用来链接2个容器 。-- link的格式 :• --link:alias • name和id是源容器的name和id,alias是源容器在link下的别名 。
在/etc/hosts 创建解析
还会创建相应的变量
更改以后,解析会发生变化,但是变量是不会变的。下面是一个测试
测试:
再开一个server1的窗口进行操作,之前的窗口用于查看现象。
docker stop demo ##停掉之前的demo
docker run -d --name demo2 nginx ##运行demo2
docker inspect demo2 ##查看demo2的ip,发现它获取了原先demo的ip
docker start demo ##重新开启demo
docker inspect demo ##可以看到demo获取的ip变成了172.17.0.4
在最初的server1窗口查看现象
变量没有发生变化,但是解析变了。
容器访问外网是通过iptables的SNAT实现的
外网如何访问容器:
•端口映射
•-p 选项指定映射端口
外网访问容器用到了docker-proxy和iptables DNAT
•宿主机访问本机容器使用的是iptables DNAT(没有也可以)
•外部主机访问容器或容器之间的访问是docker-proxy实现
做端口映射,发现有个DNAT的策略,外部80到内部容器的80端口
docker run -d --name demo -p 80:80 nginx ##指定端口映射80
iptables -t nat -nL ##可以看到防火墙的DNAT规则,当访问宿主机80时重定向到172.17.0.2的80
netstat -antlp ##可以看到ipv4和ipv6的80端口进程显示:docker-proxy。这是docker的双冗余机制
访问宿主机的ip
curl 172.25.0.1 #访问宿主机ip
开启端口映射后,会开启docker—proxy
删除端口映射规则,再次访问,发现还可以。
iptables -t nat -D DOCKER 4 ##删除DOCKER链的第四条
iptables -t nat -nL
此时还是可以通过外部进行访问的。就是因为docker时双冗余机制 。
然后再把docker-proxy进程干掉
外部访问报错
但此时容器是好的,在宿主机内部可以访问 ,因为属于同一vlan,内部数据包走的是网桥。
恢复以上机制
重新启动容器即可。
docker stop demo
docker start demo ##重启之后可以恢复这种机制
iptables -t nat -nL ##可以看到DNAT规则重新创建成功
netstat -antlp #docker-proxy重新恢复
kill -9 6017 ##再次删除docker-proxy
这次先干掉docker—proxy
外网还是可以通过访问宿主机,访问到内部仓库。
curl 172.25.0.1 #访问宿主机ip
• 跨主机网络解决方案• docker 原生的 overlay 和 macvlan• 第三方的 flannel 、 weave 、 calico• 众多网络方案是如何与 docker 集成在一起的• libnetwork docker 容器网络库• CNM ( Container Network Model )这个模型对容器网络进行了抽象• CNM 分三类组件Sandbox :容器网络栈,包含容器接口、 dns 、路由表。( namespace )Endpoint :作用是将 sandbox 接入 network ( veth pair )Network :包含一组 endpoint ,同一 network 的 endpoint 可以通信
• macvlan 网络方案实现• L i nux kernel 提供的一种网卡虚拟化技术。• 无需 Linux bridge ,直接使用物理接口,性能极好。• 在两台 docker 主机上各添加一块网卡,打开网卡混杂模式:• # ip link set eth1 promisc on
先将之前的网络清除一下。保持原生的网络。
docker rm -f demo
docker network ls
docker network prune ##删除创建的网络
docker network ls
将两台机器的eth0的混杂模式打开。
ip addr
ip link set eth0 promisc on ##打开混杂模式
ip addr #再次查看是否开启混杂模式
创建网络
docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth0 mynet1 #创建mynet1 -d 指定驱动为macvlan,指定子网和本地网络不冲突,-o指定父级即物理接口为eth0
docker network ls
docker network inspect mynet1 #看到已经创建成功
在server2上执行相同的操作
docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth0 mynet1 ##docker2上也创建网络
docker inspect mynet1 #保证server1和server2相同
创建容器
docker images
docker pull busybox #报证有镜像
docker run --rm -it --network mynet1 --ip 172.20.0.11 busybox #创建相同网段的容器
由上面发现我们是可以ping通server1上同网段的容器的。
•macvlan网络结构分析
•容器的接口直接与主机网卡连接,无需NAT或端口映射。
但是存在macvlan会独占主机网卡的问题
•macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
•vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094。
在docker1主机中重新添加一块网卡(两块网卡)
ip addr #可以看到多了eth1但是处于down
ip link set up dev eth1 ##激活eth1
ip addr
ip link set eth1 promisc on ##打开eth1的混杂模式
ip addr
docker network create -d macvlan --subnet 172.30.0.0/24 --gateway 172.30.0.1 -o parent=eth1 mynet2 ##创建mynet2
docker network inspect mynet2
docker run --rm -it --network mynet2 busybox ##指定网络运行busybox可以看到会自动分配ip
docker run --rm -it --network mynet2 --ip 172.30.0.100 busybox ##也可以自己指定IP
最好是自己指定ip,自动分配容易冲突。
docker network create -d macvlan --subnet 172.40.0.0/24 --gateway 172.40.0.1 -o parent=eth1.1 mynet3 ##创建mynet3 ,使用子网eth1.1
docker network create -d macvlan --subnet 172.50.0.0/24 --gateway 172.50.0.1 -o parent=eth1.2 mynet4 ##创建mynet4.使用子网eth1.2
docker network ls
docker network inspect mynet3
docker network inspect mynet4
ip addr
•macvlan网络间的隔离和连通
• macvlan 网络在二层上是隔离的,所以不同 macvlan 网络的容器是不能通信的。• 可以在三层上通过网关将 macvlan 网络连通起来。• docker 本身不做任何限制,像传统 vlan 网络那样管理即可。