🐳Docker网络

一.网络基础

Docker 使用到的与 Linux 网络有关的技术分别有:网络名称空间、Veth、Iptables、网桥、路由

1.什么是网络名称空间

  • 为了支持网络协议栈的多个实例,Linux 在网络协议栈中引入了网络名称空间(Network Namespace)
  • 这些独立的协议栈被隔离到不同的命名空间中
  • 处于不同的命名空间的网络协议栈是完全隔离的,彼此之间无法进行网 络通信,就好像两个“平行宇宙”
  • 通过这种对网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境

image-20201203095835616

ps : 如果不同网络名称空间之间要进行通信该怎么办呢?

2.Veth 设备对

  • 引入 Veth 设备对就是为了在不同的网络名称空间之间进行通信
  • 利用它可以直接将两个网络名称空间链接起来, Veth 设备是成对出现
  • 像一对网卡, 我们将其中一端称为另一端的 peer

image-20201203100041308

2.1.底层原理实验示例

  • 需求 : 建立两个名称空间, 并实现相互 ping
  • 查看, 添加, 删除 namespace 命令
ip netns list                # 查看
ip netns add [namespace]     # 添加
ip netns delete [namespace]  # 删除
  • 建立两个名称空间
[root@shawn ~]#ip netns add test1
[root@shawn ~]#ip netns add test2
[root@shawn ~]#ip netns list
test2
test1
  • 建立一对 veth
[root@shawn ~]#ip link add veth1 type veth peer name veth2
[root@shawn ~]#ip link

image-20201203100822449

  • 创建 veth 后, 我们将 veth 分别添加到名称空间 test1test2
[root@shawn ~]#ip link set veth1 netns test1
[root@shawn ~]#ip link set veth2 netns test2
  • 查看一下是否已经添加成功了
[root@shawn ~]#ip netns exec test1 ip link
[root@shawn ~]#ip netns exec test2 ip link

image-20201203101119038

image-20201203101141390

  • 添加完成后我们就需要为其设置 IP 了, 并将其状态 up
[root@shawn ~]#ip netns exec test1 ip addr add 172.17.0.111/20 dev veth1
[root@shawn ~]#ip netns exec test2 ip addr add 172.17.0.112/20 dev veth2
[root@shawn ~]#ip netns exec test1 ip link set dev veth1 up
[root@shawn ~]#ip netns exec test2 ip link set dev veth2 up
  • 查看 IP 是否设置成功
[root@shawn ~]#ip netns exec test1 ip a
[root@shawn ~]#ip netns exec test2 ip a

image-20201203101635359

image-20201203101654298

  • 最后, 检测一下是否能相互 ping
[root@shawn ~]#ip netns exec test1 ping 172.17.0.112
[root@shawn ~]#ip netns exec test2 ping 172.17.0.111

image-20201203101901104

image-20201203101912789

  • 成功

3.网桥(Bridge)

  • Linux 可以支持多个不同的网络,它们之间能够相互通信,就需要一个网桥, 网桥就是二层的虚拟网络设备
  • 它是把若干个网络接口“连接”起来,从而报文能够互相转发

image-20201203103048745

  • 网桥命令格式 : docker network [命令参数]
⚽查看当前系统有哪些网桥 "ls"
[root@shawn ~]#docker network ls
'''
NETWORK ID          NAME                DRIVER              SCOPE
befd59194a71        bridge              bridge              local
94f8e35f3357        host                host                local
79fb28a9a12e        none                null                local
'''

⚽创建网桥 "create"
[root@shawn ~]#docker network create shawn
ffac93578a0ce40395936d226bd097fd049ad077022419a9b6b074b6fe2f892b
[root@shawn ~]#docker network ls
'''
NETWORK ID          NAME                DRIVER              SCOPE
befd59194a71        bridge              bridge              local
94f8e35f3357        host                host                local
79fb28a9a12e        none                null                local
ffac93578a0c        shawn               bridge              local  #新建的网桥
'''

⚽查看网桥信息,格式 : "docker network inspect [网桥的名称|网桥ID]"
[root@shawn ~]#docker network inspect shawn
'''
[
    {
        "Name": "shawn",
        "Id": "ffac93578a0ce40395936d226bd097fd049ad077022419a9b6b074b6fe2f892b",
        "Created": "2020-12-03T11:56:35.554136022+08: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": {}
    }
]
'''

⚽删除网桥 "rm"
[root@shawn ~]#docker network rm shawn
shawn
[root@shawn ~]#docker network ls
'''
NETWORK ID          NAME                DRIVER              SCOPE
befd59194a71        bridge              bridge              local
94f8e35f3357        host                host                local
79fb28a9a12e        none                null                local
''' # "Shawn"被删除了

⚽清理网桥 "prune", 我们先创建多个网桥,然后一次性清除
[root@shawn ~]#docker network create shawn1
f4d2f2b57b48cd35b3cc9eddad0377cae95d213032ed0d6a92e9de9571adeb4e  #创建成功
[root@shawn ~]#docker network create shawn2
ea66ed0d06adbe7f5211f3ae38b6edeb47dffac0f53240e9204fd3dcaf4670d5  #创建成功
[root@shawn ~]#docker network create shawn3
222d6e298d6091cea0a6229e19c84825a41ea92b7c0b512db47c858dde7259f0  #创建成功
[root@shawn ~]#docker network prune
WARNING! This will remove all custom networks not used by at least one container.
Are you sure you want to continue? [y/N] y  # 问你是否要这样做"yes"
Deleted Networks:  # 将要删除以下网桥
shawn1
shawn2
shawn3
[root@shawn ~]#docker network ls
'''
NETWORK ID          NAME                DRIVER              SCOPE
befd59194a71        bridge              bridge              local
94f8e35f3357        host                host                local
79fb28a9a12e        none                null                local
'''  # 发现并没有 "shawn"系列的网桥	

4.Iptables

  • iptables是 linux 系统自带的优秀且完全免费的基于包过滤的防火墙工具、它的功能十分强大、使用非常灵活、可以对流入、流出及流经服务器的数据包进行精细的控制

5.总结

network namespace 主要提供了关于网络资源的隔离,包括网络设备、IPv4 和 IPv6 协议栈、IP 路由 表、防火墙、/proc/net 目录、/sys/class/net 目录、端口(socket)等
linux Bridge 功能相当于物理交换机,为连在其上的设备(容器)转发数据帧。如 docker0 网桥
iptables 主要为容器提供 NAT 以及容器网络安全
veth pair 两个虚拟网卡组成的数据通道。在 Docker 中,用于连接 Docker 容器和 Linux Bridge。一端在容器中作为 eth0 网卡,另一端在 Linux Bridge 中作为网桥的一 个端口

二.Docker网络模式

安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host

  • docker network ls : 查看当前系统有哪些网络(网桥)
[root@shawn ~]#docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
befd59194a71        bridge              bridge              local
94f8e35f3357        host                host                local
79fb28a9a12e        none                null                local

1.原理

  • Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0)
  • Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP, 同时Docker网桥是每个容器的默认网关
  • 因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信
  • Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器
  • 如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p-P 参数来启用,访问容器的时候就通过 [宿主机IP]:[容器向外暴露的端口] 访问容器

2.四类网络模式

网络模式 设置方法 简介
Host --network host 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
Bridge --network bridge(默认此模式) 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信
None -- network none 该模式关闭了容器的网络功能(只提供回环)
Container --network "container:[共享容器名称]" 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围

2.1、Host 模式

  • 相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址, 容易造成端口冲突
  • 但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的
  • 格式 : docker run --network host [镜像名称或ID]
[root@shawn ~]#docker run -d --network host nginx:latest

img

2.2、Container 模式

  • 这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享
  • 新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等
  • 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信
  • 格式 : docker run --network "containe:[共享容器名称]" [镜像名称或ID]
  • 实验:
⚽创建共享容器 "cont01"
[root@shawn ~]#docker run -dit --name cont01 busybox:latest sh

⚽创建链接容器 "cont02", 并指定网络模式 "container"
[root@shawn ~]#docker run -dit --name cont02 --network "container:cont01" busybox:latest sh

⚽查看两个容器的 "ip", 发现一样
[root@shawn ~]#docker exec cont01 ip a
[root@shawn ~]#docker exec cont02 ip a

image-20201203114012145

image-20201203114036897

img

2.3、None 模式

  • 该模式将容器放置在它自己的网络栈中,但是并不进行任何配置, 只提供回环
  • 该模式关闭了容器的网络功能 , 一般是因为容器并不需要网络(例如只需要写磁盘卷的批处理任务)
  • 格式 : docker run --network none [镜像名称或ID]
[root@shawn ~]#docker run -dit --network none --name none_test busybox:latest sh

img

2.4、Bridge 网桥模式

  • 相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)
  • 虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中
  • bridge模式是docker的默认网络模式,不写 --network 参数,就是bridge模式
  • 使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能

image-20201203115027432

  • 相关操作

相关操作在文章第一段第三小章 ""网桥(Bridge)""

原文地址:https://www.cnblogs.com/songhaixing/p/14078843.html