Docker-网络模式、自定义桥接、网段、手动指定IP、不同网段通信、容器通信、创建macvlan

目录

一.Docker网络 1.桥接网络 2.host网络模式 3.none模式 二.自定义网络 1.创建自定义网桥 2.自定义网段 3.手动指定ip 4.双网卡来实现不同网段间通信 三.Docker容器通信 1.内部访问外部 2.外部访问内部 3.原理 四.创建macvlan网络 1.使用eth0网卡来通信 测试 2.使用eth1网卡来通信 实现不同网段的通信 结论

我们需要将前面的docker-compose仓库停掉

[root@server1 harbor]# docker-compose stop  

请添加图片描述

一.Docker网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。
docker安装后会自动创建3种网络:bridge、host、none

1.桥接网络

安装桥接网络

ip addr show  docker0
 yum install bridge-utils -y

请添加图片描述

[root@server1 ~]# brctl show

请添加图片描述
运行一个容器查看桥接

root@server1 ~]# docker run -d --name demo nginx
[root@server1 ~]# brctl show

请添加图片描述

当我们删除掉容器之后,桥接又消失了!

docker rm -f demo
brctl show

请添加图片描述

2.host网络模式

需要我们指定network host

我们可以看到我们的桥接口上没有出现新的桥接口

[root@server1 ~]# docker run -d --name demo --network host nginx
[root@server1 ~]# brctl show
[root@server1 ~]# brctl show docker0

请添加图片描述

我们查看端口,可以发现docker运行的镜像nginx占用的是80端口!

[root@server1 ~]# netstat -antlp

请添加图片描述
这个时候,我们再运行一个容器起名为demo2,注意观察,启动之后,查看进程有两个进程demo,demo2。但是很快在查看进程,demo2消失了!
再也不会出现。
为什么?
因为加上参数–network host会占用虚拟机的80端口,所以刚开始尝试启动会看到进程,但是会被demo的80端口挤掉demo2!!

[root@server1 ~]# docker run -d --name demo2 --network host nginx
[root@server1 ~]# docker ps

请添加图片描述
我们查看日志就知道:
docker logs
请添加图片描述

3.none模式

none模式是指禁用网络功能,只有lo接口,在容器创建时使用!
先删除掉刚才创建的容器,重新运行容器:

[root@server1 ~]# docker rm -f demo   
[root@server1 ~]# docker rm -f demo2
[root@server1 ~]# netstat -antlp ##80端口随之消失!
[root@server1 ~]# docker run -it --rm --network=none busybox
/ # ip addr

请添加图片描述

请添加图片描述

我们发现ip addr的时候:只有lo接口
请添加图片描述

二.自定义网络

1.创建自定义网桥

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

创建网桥!!查看类型为brodge!!

[root@server1 ~]# docker network create mynet1
[root@server1 ~]#docker network ls

请添加图片描述
测试:
这时我们发现我们是可以ping demo可以直接成功,说明这模式是可以给提供解析的

[root@server1 ~]# docker run -d --name demo1 --network mynet1 nginx 
[root@server1 ~]# docker run -it --rm --network mynet1 busybox
/ # ip addr
/ # ping demo

请添加图片描述

请添加图片描述

请添加图片描述

注意:
我们再开一个nginx,停掉所有的demo,再次开启时,顺序反一下,查看ip变化

[root@server1 ~]# docker run -d --name demo2 --network mynet1 nginx
[root@server1 ~]# docker stop demo1
[root@server1 ~]# docker stop demo2
[root@server1 ~]# docker start demo2
[root@server1 ~]# docker start demo1
[root@server1 ~]# docker inspect  demo2
[root@server1 ~]# docker inspect  demo1
[root@server1 ~]# docker ps

[root@server1 ~]# docker attach 8095eebc598a            ##进入busybox查看
/ # ping demo2
PING demo2 (172.17.0.2):
/ # ping demo
PING demo1 (172.17.0.4): 

请添加图片描述

我们会发现之前的demo1是172.17.0.2,demo2是172.17.0.4,
现在IP地址反过来了! 为什么?
这说明:系统会自动分配ip,按照启动顺序ip单调递增,但是ping名称的时候会自动解析地址!

2.自定义网段

创建时指定参数:–subnet 、–gateway

[root@server1 ~]# docker network rm mynet1    ##定义的网络删掉
[root@server1 ~]# docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 mynet1

请添加图片描述

[root@server1 ~]# docker inspect mynet1 

请添加图片描述

3.手动指定ip

使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上

[root@server1 ~]# docker rm demo
demo
[root@server1 ~]# docker rm demo2
demo2
[root@server1 ~]# docker run -it --rm --ip 172.20.0.10 --network mynet1 busybox
[root@server1 ~]# docker run -it --rm  --network mynet1 busybox
ip addr
[root@server1 ~]# docker inspect mynet1 

请添加图片描述

请添加图片描述

请添加图片描述

4.双网卡来实现不同网段间通信

桥接到不同网桥上的容器,彼此是不通信的。
如何使两个不同网桥的容器通信呢:
使用 docker network connect命令为demo添加一块mynet1 的网卡。

[root@server1 ~]# docker rm -f demo1
[root@server1 ~]# docker network rm mynet1
[root@server1 ~]# docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 mynet2

请添加图片描述

[root@server1 ~]#docker run -d --name demo --network mynet1 --ip 172.20.0.10 nginx 

请添加图片描述

[root@server1 ~]#docker run -it --rm --network mynet1 busybox
ip addr

请添加图片描述

[root@server1 ~]#docker run -it --rm --network mynet2 busybox
ip addr

请添加图片描述

docker inspect demo 查看id
[root@server1 ~]# docker inspect  demo
[root@server1 ~]# docker network connect mynet1 demo(或1b22f***)
[root@server1 ~]# docker attach 1b22f******
ip addr

我们可以看到mynet1,mynet2的ip都出现在了里面!说明通信成功!
请添加图片描述

然后可以直接在容器里面:ping demo成功!

请添加图片描述

三.Docker容器通信

容器之间除了使用ip通信外,还可以使用容器名称通信。
dns解析功能必须在自定义网络中使用。
在容器创建时使用–network=container:vm1指定。(vm1指定的是运行的容器名)

[root@server1 ~]# docker run  -it --rm --network container:demo busybox
/ # ip addr

请添加图片描述

处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
–link 可以用来链接2个容器。
–link的格式:
–link **:alias

name是源容器的name,alias是源容器在link下的别名。

[root@server1 ~]# docker pull nginx:latest
[root@server1 ~]# docker run -d --name demo nginx
[root@server1 ~]# docker run -it --rm --link demo:web busybox
/ # ping demo
/ # env

请添加图片描述

请添加图片描述

我们再次打开一个终端链接server1:

[root@server1 ~]# docker stop demo 
[root@server1 ~]# docker run -d --name test nginx
[root@server1 ~]# docker start demo

请添加图片描述
请添加图片描述

我们再一次ping,发现ip变了(由 172.17.02 >>172.17.0.4),但是仍然可以ping名字demo成功!说明它i的名字随着IP实时更新变化的!!
请添加图片描述
这时我们查看/etc/hosts,发现他已经给我们自动修改了解析

请添加图片描述

1.内部访问外部

容器内部也是可以访问外部网络的

sysctl -a | grep ip_forward

可以看到路由转发功能是开启的为1
请添加图片描述
那么我们在容器里面可以ping baidu.com

docker run -it --rm --link demo:web busybox
ping baidu.com

请添加图片描述

2.外部访问内部

容器如何访问外网是通过iptables的SNAT实现的

外网如何访问容器:
端口映射
-p 选项指定映射端口

[root@server1 ~]# docker rm -f demo
[root@server1 ~]# docker rm -f test
docker history nginx 看到本身的端口为80
[root@server1 ~]# docker run -d --name demo -p 80:80 nginx
[root@server1 ~]# docker port demo
[root@server1 ~]# iptables -t nat -nL
[root@server1 ~]#netstat -antlp

请添加图片描述

请添加图片描述

请添加图片描述
netstat -antlp查看端口发现有docker-proxy
请添加图片描述

3.原理

外网访问容器用到了docker-proxy和iptables DNAT
宿主机访问本机容器使用的是iptables DNAT
外部主机访问容器或容器之间的访问是docker-proxy实现

测试:

[root@server1 ~]# curl 172.25.0.1
[root@server1 ~]# curl localhost

都是nginx的发布页面
请添加图片描述
现在尝试将iptables里面的策略时删除,再次测试

iptables -t nat -D DOCKER 6

请添加图片描述
已经删掉了策略!

[root@server1 ~]# iptables -t nat -nL

请添加图片描述

[root@server1 ~]# curl localhost

发现nginx发布页面还在
请添加图片描述
但是如果将docker-proxy进程杀掉,再次访问查看效果
请添加图片描述
已经访问不到了
请添加图片描述
当我们重新添加iptables策略

[root@server1 ~]# iptables -t nat -A DOCKER -p tcp --dport 80 -j DNAT --to-det 172.17.0.2:80

请添加图片描述
再次在真机上访问curl 172.25.0.1
或者在server1上访问本地localhost
发现又可以访问到nginx的发布页面了!!!
请添加图片描述所以总结:docker-proxy,iptables里面的策略至少需要存在一个才可以!!

四.创建macvlan网络

1.使用eth0网卡来通信

需要两台虚拟机server1,server2:

在两台docker主机上各创建macvlan网络
我们先用eth0网卡连作为两台虚拟机通信的网卡!

首先在server1上操作:

[root@server1 ~]# ip addr show eth0
[root@server1 ~]#ip link set eth1 promisc on
[root@server1 ~]# ip addr show eth0

请添加图片描述

我们发现ip link set eth1 promisc on打开之后,ip addr的eth0出现了promisc模式!!
请添加图片描述将之前实验的网络桥接删除掉!

docker network ls
docker network rm mynet1
docker network rm mynet2
cd harbor/
docker-compose stop

请添加图片描述

请添加图片描述
先在server1上创建指定条件的容器然后运行容器:

[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

请添加图片描述
接着在server2上操作:

删除不用的桥接网络,本人是因为做过实验所以需要删除!

[root@server2 ~]#ip link set eth1 promisc on
[root@server2 ~]# ip addr show eth0
[root@server2 ~]#docker network ls
[root@server2 ~]#docker network rm macvlan1
[root@server2 ~]#docker network rm mynet1

请添加图片描述

请添加图片描述

接着创建容器并运行和server1操作一样(只有IP不一致!)!

[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 network ls
[root@server2 ~]# docker run -it --rm --network macvlan1 --ip 172.20.0.11 busybox
ip addr

请添加图片描述

``请添加图片描述

这个时候已经完成了两台docker主机网卡的通信:

测试

在server1上的docker去ping一下server2的docker的ip地址:
发现可以通信!

ping 172.20.0.11

请添加图片描述

同理在server2上的docker去ping一下server2的docker的ip地址
也是可以成功的!

ping 172.20.0.10

2.使用eth1网卡来通信

首先需要在server1,2上再添加一块网卡:

virt-manager
分别选择两个虚拟机
添加网卡:add hardware
network网卡:virtio桥接的模式
finish

请添加图片描述

请添加图片描述

添加网卡之后,查看eth1可以看到没有ip只是一个网卡
ip link set up eth1让它启用!

 ip addr show eth1
 ip link set up eth1

请添加图片描述

我们需要编辑网卡的配置文件

cd /etc/sysconfig/network-scripts
cp ifcfg-eth0 ifcfg-eth1
vim ifcfg-eth1

请添加图片描述

请添加图片描述

让eth0网卡不能获得ip,随网络服务启动

请添加图片描述

重新激活网卡

ifup eth1

请添加图片描述

我们查看一下eth1

 ip addr show eth1

发现已经激活但是promisc模式还没有打开!
请添加图片描述
开启promisc模式

ip link set eth1 promisc on

请添加图片描述

创建容器并运行,注意网段需要改变一下和前面eth0不一样172.21..

[root@server1 ~]#docker network  create -d macvlan --subnet 172.21.0.0/24 --gateway=172.21.0.1 -o parent=eth1.1 macvlan2

[root@server1 ~]# docker run -it --rm --network macvlan2 --ip 172.21.0.10 busybox
ip addr

请添加图片描述
在server2也需要激活网卡打开promisc模式

ip link set up eth1
ip link set eth1 promisc on
ip addr show eth1

请添加图片描述

请添加图片描述

在server2也需要创建容器并运行:

[root@server2 ~]#docker network  create -d macvlan --subnet 172.21.0.0/24 --gateway=172.21.0.1 -o parent=eth1.1 macvlan2

[root@server2 ~]# docker run -it --rm --network macvlan2 --ip 172.21.0.11 busybox
ip addr

请添加图片描述
测试:
server1里可以ping通server2 的ip;172.21.0.11

ping 172.21.0.11
请添加图片描述
同理server2也可以ping通server1
ping 172.21.0.10
请添加图片描述

实现不同网段的通信

我们在server2上运行前面的macvlan1

[root@server2 ~]# docker run  --rm --network macvlan1 --ip 172.20.0.11 busybox

请添加图片描述

在server1上
如何使两个不同网桥的容器通信呢:
使用 docker network connect命令为demo添加一块macvlan1 的网卡。

先将macvlan2刚才的进程结束:
docker ps
docker rm -f ********
docker run -d --name demo --network macvlan2 --ip 172.21.0.10 nginx
docker network connect macvlan1 demo
docker inspect demo

请添加图片描述

请添加图片描述

然后运行容器,为demo添加一块macvlan1 的网卡。请添加图片描述

我们可以看到demo的信息中会自动生成和 macvlan1同网段172.20.*.*的ip:172.20.0.2
请添加图片描述

测试:
我们发现不同网段 172.21.0.10还是不能通信,但是生成的Ip172.20.0.2可以访问。

ping 172.21.0.10
ping 172.20.0.2

请添加图片描述

结论

我们得出结论:不同网段的ip是无法互通的,但是两个处于不同网段的容器可以通过docker network connect macvlan1 demo的方式来生成同一网段IP地址的方式来实现容器间的通信!!

在server2上去访问172.25.0.2

curl 172.25.0.2

成功!

请添加图片描述

来源url
栏目