目录
- 一.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.11ping 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
成功!