1.Docker网络
docker的网络功能还是相对薄弱的。
docker安装后会自动创建3种网络:bridge、host、none
1.1桥接网络
前提:
将前面的docker-compose仓库停掉
docker-compose stop
安装桥接网络
yum install bridge-utils -y
brctl show
docker run -d --name demo nginx
docker inspect demo 查看信息ip为 0.2
docker run -it --rm busybox
ip addr ##ip为0.3
1.2.host网络模式
docker run -d --name demo --network host nginx
查看端口可以发现docker运行的镜像nginx占用的是80端口
参数 –network host会占用虚拟机的80端口. 别的nginx不会使用80端口
1.3.none模式
docker run -it --rm --network none busybox
只有lo接口
2.自定义网络
2.1.创建自定义网桥
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
创建网桥 查看类型为bridge
docker network create mynet1 (默认创建桥接)或 docker network create -d bridge mynet1
docker network ls
测试:
docker run -d --name demo1 --network mynet1 nginx
docker run -it --rm --network mynet1 busybox
ping demo1
可以ping demo可以直接成功,说明此模式可以给提供解析
并且系统会自动分配ip,按照启动顺序ip单调递增,但是ping名称的时候会自动解析地址
2.2.自定义网段
docker network rm mynet1
docker network create -d bridge --subnet 10.0.0.0/24 --gateway 10.0.0.1 mynet1
docker inspect mynet1 ##查看信息
2.3.手动指定ip
使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上
docker run -d --name web1 --network mynet1 nginx
docker run -it --rm --network mynet1 busybox
/ # ip addr
254: eth0@if255: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping web1
PING 10.0.0.1 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.043 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.042 ms
--- 10.0.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.042/0.042/0.043 ms
cat /etc/hosts
自动解析
也可以ping通网关
2.4.双网卡来实现不同网段间通信
桥接到不同网桥上的容器,彼此是不通信的。
docker network create -d bridge --subnet 20.0.0.0/24 --gateway 20.0.0.1 mynet2
docker run -it --rm --network mynet2 busybox
ping不通
docker psdocker network connect mynet1 elastic_brahmagupta 后
ping web1/web2
成功
原理是在 busybox中添加了10.0.0的ip
3.Docker容器通信
容器之间除了使用ip通信外,还可以使用容器名称通信。
dns解析功能必须在自定义网络中使用。
在容器创建时使用–network container:web1指定。
docker run -it --rm --network container:web1 busyboxplus
处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
curl localhost
–link 可以用来链接2个容器。
–link的格式:
–link **:alias
name是源容器的name,alias是源容器在link下的别名。
docker run -d --name web1 nginx
docker run -it --rm --link web1:nginx busyboxplus
ping web1
cat /etc/hosts
env
再次打开一个终端链接server5
docker stop web1
docker run -d --name web2 nginx
docker start web1
我们再一次ping,发现ip变了(由 172.17.02 >>172.17.0.4),但是仍然可以ping名字web1 或nginx 成功 说明它i的名字随着IP实时更新变化的
这时我们查看/etc/hosts,也已经给我们自动修改了解析
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4 nginx cc04bfdcf946 web1
172.17.0.3 01239d8f8819
3.1.内部访问外部
容器内部也是可以访问外部网络的
sysctl -a | grep ip_forward
我们在容器里面可以ping baidu.com
docker run -it --rm --link web1:nginx busybox
ping baidu.com
3.2.外部访问内部
容器如何访问外网是通过iptables的SNAT实现的
外网访问容器
端口映射
-p 选项指定映射端口
先删除之前的容器
docker run -d --name web1 -p 80:80 nginx
iptables -t nat -nL
netstat -antlp
发现有docker-proxy
3.2.1原理
外网访问容器用到了docker-proxy和iptables DNAT
宿主机访问本机容器使用的是iptables DNAT
外部主机访问容器或容器之间的访问是docker-proxy实现
测试:
curl 172.25.76.5
curl localhost
现在尝试将iptables里面的策略删除,再次测试
iptables -t nat -F
iptables -t nat -nL
curl localhost
是因为docker-proxy还在
如果将docker-proxy进程杀掉 就没了
kill -9 28716 28721
再次访问
当我们重新开启docker
iptables 会重新生成
systemctl restart docker
iptables -t nat -I POSTROUTING -s 172.17.0.0/16 -j MASQUERADE
`curl 172.25.76.5
又可以访问到nginx的发布页面
从结果得知:
docker-proxy,iptables里面的策略至少需要存在一个才可以
4.创建macvlan网络
实验环境构建:
server5(原虚拟机):
cat /etc/yum.repos.d/dvd.repo
[dvd]
name=rhel7.6
baseurl=http://172.25.76.250/rhel7.6
gpgcheck=0
[docker]
name=docker-ce
baseurl=http://172.25.76.250/20
gpgcheck=0
scp /etc/yum.repos.d/dvd.repo root@172.25.76.4:/etc/yum.repos.d/
scp /etc/sysctl.d/docker.conf server4:/etc/sysctl.d/
server4:
yum install docker-ce -y 安装
systemctl enable --now docker
安装docker的步骤略过 请看上一篇博客
加busyboxplus
docker pull radial/busyboxplus
docker tag radial/busyboxplus:latest busyboxplus:latest
docker rmi radial/busyboxplus:latest
4.1.使用eth1网卡来通信
server4(5):都需要做同样的操作
都添加一个网卡
ip addr show eth1 #查看ip
cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth1
vim /etc/sysconfig/network-scripts/ifcfg-eth1
BOOTPROTO=none
ONBOOT=yes
DEVICE=eth1
ip link set eth1 promisc on
ifup eth1
发现ip addr的eth1出现了promisc模式
server5:
将之前实验的网络桥接删除掉
先在server5上创建指定条件的容器然后运行容器:
docker network create -d macvlan --subnet 10.0.0.0/24 --gateway=10.0.0.1 -o parent=eth1 macvlan1
docker run -it --rm --network macvlan1 --ip 10.0.0.10 busyboxplus
ip addr
在server4上:
创建容器并运行和server5操作一样(只有IP不一致!)!
docker network create -d macvlan --subnet 10.0.0.0/24 --gateway=10.0.0.1 -o parent=eth1 macvlan1
docker run -it --rm --network macvlan1 --ip 10.0.0.11 busyboxplus
ip addr
测试:
在server5上的docker去ping一下server4的docker的ip地址:
server5:
docker run -d --name web1 --network macvlan1 --ip 10.0.0.10 nginx
server4:
docker run -it --rm --network macvlan1 --ip 10.0.0.11 busyboxplus
ping 10.0.0.10
curl 10.0.0.10
成功
也可用虚拟VLAN 网卡进行实验:
在server4和server5:
docker network create -d macvlan --subnet 20.0.0.0/24 --gateway 20.0.0.1 -o parent=eth1.1 macvlan2
ip addr
在server5上创建一个ip为20.0.0.10 而server4则为20.0.0.11的容器
[root@server5 ~]# docker run -it --rm --network macvlan2 --ip 20.0.0.10 busyboxplus
[root@server4 ~]# docker run -it --rm --network macvlan2 --ip 20.0.0.11 busyboxplus
ipaddr
查看ip
server5:
server4:
ping 20.0.0.10
成功
结论
不同网段的ip无法互通 但两个处于不同网段的容器可以通过docker network connect macvlan1 的方式来生成同一网段IP地址的方式来实现容器间的通信。
关于虚拟VLAN网卡:
虚拟VLAN网卡也不是实际上的网络接口设备,也可以作为网络接口在系统中出现,但他们没有自己的配置文件而只是通过将物理网加入不同的VLAN而生成的VLAN虚拟网卡。它们的网络接口名是eth0.1、eth1.1这种名字。
注:当需要启用VLAN虚拟网卡工作的时候,关联的物理网卡网络接口上必须没有IP地址的配置信息,并且,这些主物理网卡的子网卡也必须不能被启用和必须不能有IP地址配置信息。