文章目录
一、初识docker网络
1、docker0虚拟网桥
docker启动之后,在本机网络中会出现一个docker0的虚拟网桥,docker就是在这个网桥的基础上进行网络通讯的。
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:55ff:fe91:27de prefixlen 64 scopeid 0x20<link>
ether 02:42:55:91:27:de txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 446 (446.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.56.10 netmask 255.255.255.0 broadcast 192.168.56.255
inet6 fe80::a00:27ff:fedd:f690 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:dd:f6:90 txqueuelen 1000 (Ethernet)
RX packets 24575 bytes 1971420 (1.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 20128 bytes 2203182 (2.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2、docker网络常用基本命令
# 查看网络(安装docker会默认创建3大网络模式)
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ff578279c4c5 bridge bridge local
83c25282c4d8 host host local
6451c3243251 none null local
# 查看网络源数据
docker network inspect XXX网络名字
# 查看 bridge 网络的详细信息
[root@localhost ~]# docker network inspect bridge
# 删除网络
docker network rm XXX网络名字
# 查看帮助
[root@localhost ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
3、docker网络可以解决的问题
容器间的互联和通信以及端口映射。
容器IP变动时候可以通过服务名直接网络通信而不受到影响。
二、docker网络模式
1、四种网络模式
docker总共有四种网络模式:
bridge模式:使用--network bridge指定,默认使用docker0
host模式:使用--network host指定
none模式:使用--network none指定
container模式:使用--network container:NAME或者容器ID指定
网路模式 | 简介 |
---|---|
bridge | 为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,默认为该模式 |
host | 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 |
none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,IP等 |
container | 新建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等 |
2、容器实例内默认网络IP生产规则
(1)我们分别启动两个ubuntu容器,并且使用ctrl + p + q退出使其后台运行
docker run -it --name u1 ubuntu bash
docker run -it --name u2 ubuntu bash
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6bb36da63758 ubuntu "bash" 56 seconds ago Up 55 seconds u2
ade32205d652 ubuntu "bash" About a minute ago Up About a minute u1
(2)我们分别查看u1和u2的网络情况
[root@localhost ~]# docker inspect u1 | tail -n 20
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ff578279c4c58fa49282cbc08832a43eab6ce13d3490fb3c92be3d5d269559d1",
"EndpointID": "cdb142d2f794f59fdfb1ac3f43ce16875c9de5e6ede5507c0bb255caff5c4063",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
[root@localhost ~]# docker inspect u2 | tail -n 20
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ff578279c4c58fa49282cbc08832a43eab6ce13d3490fb3c92be3d5d269559d1",
"EndpointID": "10c4b59a121375c0345b5488148b18f0833f62f0726e9eec38482569ddc0e374",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
我们可以看出,u1的ip是172.17.0.2,u2的ip是172.17.0.3,并且都使用bridge的模式。
(3)我们删掉u2,再启动一个u3
docker rm -f 6bb36da63758
docker run -it --name u3 ubuntu bash
[root@localhost ~]# docker inspect u3 | tail -n 20
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ff578279c4c58fa49282cbc08832a43eab6ce13d3490fb3c92be3d5d269559d1",
"EndpointID": "9643672d66cd69ed297556f3b2345199eeff3d77e8af977d0946be67a52a82ee",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
我们查看u3的网络,发现u3的网络和原来的u2是一样的,对于这种变化不定的网络,我们是需要进行配置的。
3、bridge模式
Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层
连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
2 docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址
3 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。
3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
3.2 每个容器实例内部也有一块网卡,每个接口叫eth0;
3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。
我们分别启动两个容器,对网络进行验证,发现确实是容器中eth0和宿主机veth一一对应的。
4、host模式
host模式直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 网桥转换。
容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
# 使用host模式启动tomcat,如果仍然指定端口的话,会出现警告
docker run -d -p 8083:8080 --network host --name tomcat tomcat
# WARNING: Published ports are discarded when using host network mode
# 不需要指定端口
docker run -d --network host --name tomcat tomcat
# 使用host模式不会有端口映射
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8d2e6b0dd23 tomcat "catalina.sh run" 2 seconds ago Up 1 second 0.0.0.0:8083->8080/tcp, :::8083->8080/tcp tomcat2
afca1328da50 tomcat "catalina.sh run" 3 minutes ago Up 3 minutes tomcat
docker启动时指定–network=host或-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。
此时,不管是在宿主机还是容器中,使用ip addr显示的内容是一样的,因为都是使用的宿主机的网卡。
5、none模式
禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)
# 使用none模式
docker run -d -p 8084:8080 --network none --name tomcatnone tomcat
此时,进入容器之后,使用ip addr命令,只有127.0.0.1网络。
none模式几乎很少用。
6、container模式
新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
# 启动一个unbutu
docker run -it --name u1 ubuntu bash
# 启动第二个
docker run -it --network container:u1 --name u2 ubuntu bash
我们分别在两个容器中使用ip addr查看网络,发现是一致的:
此时我们关闭u1容器,发现u2容器之后一个lo回环地址了,再启动u1也不会出现新的网络。
五、自定义网络模式
1、过时的docker link
官网提示,link模式在后续版本可能会被移除掉。
官网:https://docs.docker.com/network/links/
2、使用自定义网络前
# 启动一个unbutu,默认使用网桥模式bridge
docker run -it --name u1 ubuntu bash
# 启动第二个,默认使用网桥模式bridge
docker run -it --name u2 ubuntu bash
通过ip addr我们发现,u1的ip是172.17.0.2,u2的ip是172.17.0.3,使用ping命令可以互相ping通。
但是互相ping名字的话,会出现服务找不到的问题。
3、使用自定义网络
# 新建自定义桥接网络,自定义网络默认使用的是桥接网络bridge
[root@localhost /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ff578279c4c5 bridge bridge local
83c25282c4d8 host host local
6451c3243251 none null local
[root@localhost /]# docker network create my_network
a83033be4cba946e5bd8795401a0710aac368f71989e247bebe2a32b4b80e6a7
[root@localhost /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ff578279c4c5 bridge bridge local
83c25282c4d8 host host local
a83033be4cba my_network bridge local
6451c3243251 none null local
# 启动ubuntu容器,并指定自定义的网络
docker run -it --network my_network --name u3 ubuntu
docker run -it --network my_network --name u4 ubuntu
# ping ip 可以ping通
ping 172.19.0.2
# ping服务名,也可以ping通!
ping u4
4、总结
自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)