作为小笔记参考!!!
这个文主要写了docker 单主机网络类型 none host container bridge
前面三个是简单的带过 最后会详细的说下bridge网络
docker安装的时候会默认创建三个不同的网络:
[^_^] kfk ~# docker network ls
NETWORK ID NAME DRIVER SCOPE
86c72e7bd780 bridge bridge local
753952a6771e host host local
73bd69e2e4f3 none null local
none 网络
none 没有其他网卡,只能ping通自己,不能被其他容器访问,这种场景很少使用,一般对安全性要求较高的项目会使用
创建一个none网络的容器
docker run -itd --name none_test1 --network none busybox
查看下 容器的信息
"Containers": {
"2edae895834c595e8e5177b9b4641e9054f319398bffb082bb5cb73f8e937911": {
"Name": "none_test1",
"EndpointID": "eabb52395e918fb74c0cdf07956e713c475e77423704029c2e1821678d8e270a",
"MacAddress": "",
"IPv4Address": "",
"IPv6Address": ""
}
可以看到 她没有物理地址以及ip地址,进入到容器中看下 只有一个lo本地回环,没有其他网络
[^_^] kfk ~# docker exec -it none_test1 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
host 网络
host 共享物理机上的网络协议栈,他会和主机产生相同的网络,可以连接到主机网络上,直接连接到docker作用是性能好,但是他会牺牲一部分端口灵活性。
采用host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,若宿主机具有公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换,而且由于容器通信时,不再需要通过linux bridge等方式转发或数据包的拆封,性能上有很大优势。当然,这种模式有优势,也就有劣势,主要包括以下几个方面:
1. 最明显的就是容器不再拥有隔离、独立的网络栈。容器会与宿主机竞争网络栈的使用,并且容器的崩溃就可能导致宿主机崩溃,在生产环境中,这种问题可能是不被允许的。
2. 容器内部将不再拥有所有的端口资源,因为一些端口已经被宿主机服务、bridge模式的容器端口绑定等其他服务占用掉了。
创建一个 host网络
docker run -itd --name host_test1 --network host busybox
查看容器信息
"Containers": {
"969e44eb8f62c87ab29f8f34a04c1d26433f50b13f7fc3dd6ba23182351921e6": {
"Name": "host_test1",
"EndpointID": "046bd2985d4586ca584cbee37b855087c676159f136a448fcf96c244e3e5c80e",
"MacAddress": "",
"IPv4Address": "",
"IPv6Address": ""
}
通过 docker network inspect host 查看到 信息是和none是一样的
进入到容器中 查看网络信息 下面的信息 在宿主机上 查看到的是一样的
[^_^] kfk ~# docker exec -it host_test1 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:6f:5e:ed brd ff:ff:ff:ff:ff:ff
inet 192.168.237.128/24 brd 192.168.237.255 scope global dynamic ens33
valid_lft 1741sec preferred_lft 1741sec
inet6 fe80::20c:29ff:fe6f:5eed/64 scope link
valid_lft forever preferred_lft forever
docker0 Link encap:Ethernet HWaddr 02:42:C4:59:A6:16
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:c4ff:fe59:a616/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:438 (438.0 B)
container 网络
container模式,即join模式 与host模式类似,只是容器将与指定的容器共享网络命名空间。这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。
当运行一个纯web服务的容器(没有base镜像的支持),那这个容器只能提供软件的运行,可以通过container 将容器连接在一起
创建一个没有base环境的容器
[^_^] kfk ~# docker run -d --name join_web httpd
进入这个容器 查看信息
[T_T] kfk ~# docker exec -it join_web sh
# ls
bin build cgi-bin conf error htdocs icons include logs modules
# ip a
sh: 2: ip: not found
#
🍙 注意 在没有base镜像基础支持之下,在软件型的镜像中,它只能提供最小化的运行,仅仅提供软件的运行,而不是提供一个完整系统的使用
通过container将容器和其他镜像连接在一起 就可以使用sh命令查看网络信息啦
[^_^] kfk ~# docker run -it --network container:web --rm busybox sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
343: eth0@if344: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
345: eth1@if346: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:58:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.88.0.3/24 brd 172.88.0.255 scope global eth1
valid_lft forever preferred_lft forever
bridge 网络
bridge模式是docker默认,在创建docker后 会默认创建docker0这个网卡。在这种模式下,docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的docker0网桥,容器可以与宿主机乃至外界进行网络通信。
容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接到docker0这个网桥上的,它可以作为虚拟交换机使容器可以相互通信。然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以访问容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,将宿主机上的端口端口流量转发到容器内的端口上.
bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。(来自网络 因为比我解释的好)
如上图,容器web通过一对veth pair连接 veth 另一边通过桥接 连接到docker0上 docker0和ens33 在相同设备中 通过路由转发 连接外网
创建一个名字为my_net的bridge的网卡(随机网段)
[^_^] kfk ~# docker network create --driver bridge my_net
[^_^] kfk ~# docker network ls
NETWORK ID NAME DRIVER SCOPE(生效范围)
86c72e7bd780 bridge bridge local
753952a6771e host host local
d3e083fe5bee my_net bridge local
73bd69e2e4f3 none null local
查看网卡信息
[^_^] kfk ~# docker network inspect my_net
[
{
"Name": "my_net",
"Id": "d3e083fe5bee04d6e9589374add2cff90f8ebae4e9ff5a63b9d99a9abdc6cfa5",
"Created": "2021-11-30T20:37:59.732821062-05:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
可以看到他的网段,会根据已存在的bridge网卡自动增加
默认创建的容器 使用的是docker0网卡,如果不小心把docker0网卡移除,可以重启docker 会自动在创建一个docker0网卡
[^_^] kfk ~# docker run -itd --name 0_test busybox
查看网络信息
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
349: eth0@if350: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
349 这个是容器的ip 后面eth0@if350 @的意思是连接 本地的eth0 349pair网卡和宿主机veth350相连,这里看不到350的信息 可以在宿主机 ip a查看
350: veth1df0c5f@if349: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 2a:7b:22:78:de:15 brd ff:ff:ff:ff:ff:ff link-netnsid 4
inet6 fe80::287b:22ff:fe78:de15/64 scope link
valid_lft forever preferred_lft forever
查看桥接网卡 上面会生成一个新的网卡接口
docker0 8000.0242c459a616 no veth1df0c5f
在查看bridge网卡的信息 会发现 里面多了一条容器的信息
{
"Name": "bridge",
"Id": "86c72e7bd78059192fccac08c830d93051ce0f23bcf53732143d5d818466fb2e",
"Created": "2021-11-30T21:17:41.366025036-05:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"b97896268be5ff18c2ed2143ae387904fc6d8014b1cdb9caef4765695a2ebe88": {
"Name": "web",
"EndpointID": "02b864684ec05ceaf6addc851c972c2155ff5cc32930c55d88810adc10062ddd",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
可以看到 网卡的网段,网关信息,以及容器的mac地址和ip
创建自定义桥接网络(手动指定ip地址)
[^_^] kfk ~# docker network create --driver bridge --subnet 172.88.0.0/24 --gateway 172.88.0.1 my_net2
创建一个名为my_net2的网卡 网关是172.88.0.0 子网掩码24位 网关位172.88.0.1
查看这个网卡的详细信息
{
"Name": "my_net2",
"Id": "1c8654d79d7f499a75cb6138fcdcf94092c0aee14c05a3a651629fc3c7ec39ce",
"Created": "2021-12-01T01:46:49.892944972-05:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.88.0.0/24",
"Gateway": "172.88.0.1"
}
]
},
创建一个容器,指定桥接那块网卡
[^_^] kfk ~# docker run -itd --name test2 --network my_net2 busybox
以下内容是这张图的解释
docker0 里面的容器可以和 my_net2网卡的ip ping通,相反 my_net2中的容器也可以和docker0网卡进行通信,他们之间实现通讯是通过l路由转发(ip_forward)可以通过ip r 来查看 [ 检查路由/默认网关的信息查看路由信息会给我们显示数据包到达目的地的路由路径。要查看网络路由信息,使用ip route show命令(简写 ip r)],
可以看到 这几个网段是可以互相转发的,不能通讯的问题就在于防火墙
iptables-save 可以看到有几段 ISOLATION (孤岛) 也就是说隔离起来的岛落
这里的意思是 # DOCKER-ISOLATION-STAGE-1 链的请求如果来自 docker0 所在网段, 而且目标网段不属于 docker0 所在网段, 那么跳转到 DOCKER-ISOLATION-STAGE-2 处理
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
# DOCKER-ISOLATION-STAGE-2 链的请求如果目标的网段为 br-1c8654d79d7f 所在网段则丢弃请求
-A DOCKER-ISOLATION-STAGE-2 -o br-1c8654d79d7f -j DROP
这里可以看到 docker0 和其他的主机之间是不通的,只能通到网卡,再往里面 防火墙给挡了,如果想通讯的话 可以通过下面的方法,给某一个容器多添加一块网卡
[T_T] kfk ~# docker network connect my_net2 web
进入到容器中 查看网卡信息
[T_T] kfk ~# docker run -it --network container:web --rm busybox sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
343: eth0@if344: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
345: eth1@if346: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:58:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.88.0.3/24 brd 172.88.0.255 scope global eth1
valid_lft forever preferred_lft forever
可以看到 这个容器拥有了一个新的网卡 ip是172.88 这个网段,docker0 里面的容器就可以和my_net2里面的容器进行通讯
如果觉得我的文对你有帮助的话 可以关注下我的公众号 一般写文第一时间发布到公众号中
公众号名称 咕咕崽
二维码: