Linux - Namespace:

目前,Linux实现了六种不同类型的命名空间。每个命名空间的目的都是将一个特定的全局系统资源包装在一个抽象中,使得它看起来像名称空间内的进程,它们拥有自己独立的全局资源实例。命名空间的总体目标之一是支持容器的实现,这是一种轻量级虚拟化(以及其他目的)工具,它为一组进程提供了一种愿景,即它们是系统上唯一的进程。

如果要深入研究docker技术,linux namespace是必须掌握的基础知识。

Linux的六种Namespace:

名称 系统调用参数 相关内核版本 作用
Mount namespace (挂载命名空间) CLONE_NEWNS Linux 2.4.19 提供磁盘挂载点和文件系统的隔离能力
UTS namespace(UTS命名空间) CLONE_NEWUTS Linux 2.6.19 提供主机名隔离能力
IPC namespace(IPC命名空间) CLONE_NEWIPC Linux 2.6.19 提供进程间通信的隔离能力
PID namespace(PID命名空间) CLONE_NEWPID Linux 2.6.24 提供进程隔离能力
Network namespace(网络命名空间) CLONE_NEWNET 始于Linux 2.6.24,在Linux 2.6.29中完成 提供网络隔离能力
User namespace(用户命名空间) CLONE_NEWUSER 始于Linux 2.6.23,在Linux 3.8中完成 提供用户隔离能力

参考资料:https://lwn.net/Articles/531114/

参考资料:https://www.cnblogs.com/linhaifeng/p/6657119.html

网络常用命令:

命令 说明
ping 基于(ICMP)协议,验证IP地址的可达性
telnet 检查服务的可用性
brctl 网桥命令工具(bridge-utils)
ifconfig 用于显示或配置网络设备
ip ip命令和ifconfig类似但ip功能更强大用于网络管理
route 路由管理
dhclient 使用DHCP协议在局域网取得IP
netstat 查看网络接口所监听的端口
host 分析测试域名(bind-utils)
tracerout 跟踪IP路由

Docker - bridge:

Bridge网络是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。

Brdige桥接模式为Docker Container创建独立的网络栈,保证容器内的进程组使用独立的网络环境,实现容器间、容器与宿主机之间的网络栈隔离。另外,Docker通过宿主机上的网桥(docker0)来连通容器内部的网络栈与宿主机的网络栈,实现容器与宿主机乃至外界的网络通信。

查看当前网络:

[vagrant@docker-host ~]$ docker network  ls
NETWORK ID          NAME                DRIVER              SCOPE
b2e275fbd33a        bridge              bridge              local
93e25809038e        host                host                local
e2f76a9525ed        mynet               bridge              local
acb32226a73d        none                null                local

Docke会自动为每个主机创建三个网络:

名称 作用
bridge bridge网络是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将并将一个主机上的Docker容器连接到一个虚拟网桥上。当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
none 在none模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
host 如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。

容器之间的网络:

查看网络:

[vagrant@docker-host ~]$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b2e275fbd33a        bridge              bridge              local
93e25809038e        host                host                local
e2f76a9525ed        mynet               bridge              local
acb32226a73d        none                null                local

查看bridge网络信息:

[vagrant@docker-host ~]$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "b2e275fbd33af36182e5c7a6468ac98c4e98a9063e3a3dae83b7765144a759bb",
        "Created": "2018-06-14T11:30:28.762530396Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

创建容器:

[vagrant@docker-host ~]$ docker run  -d -it --name bbox1 busybox
f5afcc66498d2ed8b25a27177986f76362327c5d8c8a0ebf1adb0c03e6a6dbcb
[vagrant@docker-host ~]$ docker run  -d -it --name bbox2 busybox
2bee3ba2ea6070daf4a9c0ace26bcd533b0dcd15ac121ba46b4389a7795e31c3

此时再次查看docker的bridge网络,会发现Container中多出了两个网络信息:

"ConfigOnly": false,
        "Containers": {
            "1b0a788f72866e87e7d244bfa1e07dc9c02d9f98d4813259f5a47ef76596fda3": {
                "Name": "bbox2",
                "EndpointID": "fd6c43f1e1699777b4b936cccad4450e75dce6f8ec0ca1dc974bc3739b066e41",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "d28333de578e1cd2007b9fa4c22807a59d61b53bc451017d83292237cdd37639": {
                "Name": "bbox1",
                "EndpointID": "86334095fbf03eaa0cfe2d2082ac119ee5af10e00fed4df37cb1e6909fddd465",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        }

由此可见,创建docker容器默认使用的网络是bridge网络,而且默认容器之间是可以相互通信的。

[vagrant@docker-host ~]$ docker ps -a   # 查看容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1b0a788f7286        busybox             "sh"                2 minutes ago       Up 2 minutes                            bbox2
d28333de578e        busybox             "sh"                3 minutes ago       Up 3 minutes                            bbox1
[vagrant@docker-host ~]$ docker exec -it bbox1 /bin/sh  # 进入bbox1 
/ # ifconfig   # 查看网络信息
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ping 172.17.0.3   # 检查与bbox2容器之间的网络是否是可通的
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.101 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.097 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.102 ms
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.083/0.095/0.102 ms

创建网络:

创建新的网络:

[vagrant@docker-host ~]$ docker network create -d bridge mybridge
e2f76a9525edd675a14ed84b228d114b2694cb636deb49719e424a05776a8384

查看创建的网络:

[vagrant@docker-host ~]$ docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "3232217a802ec7a9366afdc37bb1148a708f63f5db0e73113b35fb6adbf48ca7",
        "Created": "2018-06-15T11:38:34.313795476Z",
        "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": {}
    }
]
[vagrant@docker-host ~]$ brctl show
bridge name			bridge id			STP enabled		interfaces
br-3232217a802e		8000.02425d812be6		no
docker0				8000.024276ae1bbc		no			veth538e4f9
														vethc2ffaee

这个br-3232217a802e就是刚才创建的bridge网络mybrdge

创建容器指定网络:

[vagrant@docker-host ~]$ docker run  -d -it --name bbox3 --network mybridge busybox
55734c3f7b2e0e61070b07e69ce8b6cc7f1e28fb05090858e1f619812e740387 

创建完成后,再次查看网桥:

[vagrant@docker-host ~]$ brctl  show
bridge name			bridge id			STP enabled	interfaces
br-3232217a802e		8000.02425d812be6		no	vethc2922ce
docker0				8000.024276ae1bbc	no	veth538e4f9
								vethc2ffaee

可以看出br-3232217a802e上多了一个interfaces。

查看Bridge网络:

[vagrant@docker-host ~]$ docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "3232217a802ec7a9366afdc37bb1148a708f63f5db0e73113b35fb6adbf48ca7",
        "Created": "2018-06-15T11:38:34.313795476Z",
        "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": {
            "55734c3f7b2e0e61070b07e69ce8b6cc7f1e28fb05090858e1f619812e740387": {
                "Name": "bbox3",
                "EndpointID": "0cca477b8c13b65ee6c301c7c71096e90f94c01a13c07614a299af5e102a3b97",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

可以看出 container部分多了一个容器 bbox3

将其他容器连接至创建的网络中:

将创建的bbox2连接至mybridge中:

[vagrant@docker-host ~]$ docker network connect mybridge bbox2

再次查看网络:

See 'docker --help'
[vagrant@docker-host ~]$ docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "3232217a802ec7a9366afdc37bb1148a708f63f5db0e73113b35fb6adbf48ca7",
        "Created": "2018-06-15T11:38:34.313795476Z",
        "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": {
            "1b0a788f72866e87e7d244bfa1e07dc9c02d9f98d4813259f5a47ef76596fda3": {
                "Name": "bbox2",
                "EndpointID": "d00a5c16de03fdb0b6f93eb275ba1e0415aa6496da17e4279dda547c70871ca1",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "55734c3f7b2e0e61070b07e69ce8b6cc7f1e28fb05090858e1f619812e740387": {
                "Name": "bbox3",
                "EndpointID": "0cca477b8c13b65ee6c301c7c71096e90f94c01a13c07614a299af5e102a3b97",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

会发现Containers中多了一个bbox2

查看网桥:

[vagrant@docker-host ~]$ brctl  show
bridge name			bridge id		STP enabled		interfaces
br-3232217a802e		8000.02425d812be6	no			veth7d193ff
													vethc2922ce
docker0				8000.024276ae1bbc	no			veth538e4f9
													vethc2ffaee

会发现br-3232217a802e上又多了一个interfaces

多容器使用一个bridge网络,容器之间是可以互相通信的。

Docker - link:

在使用Docker的时候,经常可能需要连接到其他的容器,比如:web服务需要连接数据库。按照往常的做法,需要先启动数据库的容器,映射出端口来,然后配置好客户端的容器,再去访问。其实针对这种场景,Docker提供了--link 参数来满足。

使用link建立容器连接:

当前有两个容器,bbox1bbox2

[vagrant@docker-host ~]$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1b0a788f7286        busybox             "sh"                2 hours ago         Up 2 hours                              bbox2
d28333de578e        busybox             "sh"                2 hours ago         Up 2 hours                              bbox1

再创建一个容器bbox4 链接到bbox1上去:

[vagrant@docker-host ~]$ docker run  -d -it --name bbox4 --link bbox1 busybox 
b90ae3c8bc107e5f53879449997a95ea313c388e959e44f75ded764f8f2ea9d3

进入到bbox3容器中测试网络:

[vagrant@docker-host ~]$ docker exec -it bbox4 /bin/s
/ # ping bbox1
PING bbox1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.087 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.099 ms
64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.085 ms
^C
--- bbox1 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.085/0.091/0.099 ms
/ # cat /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.2	bbox1 d28333de578e
172.17.0.4	b90ae3c8bc10

可以看出在使用--link的时候docker在容器的/etc/hosts下添加了一个DNS服务。

Done.