该文为《深入浅出Docker》的学习笔记,感谢查看,如有错误,欢迎指正
Docker 网络架构由3个主要部分构成:
1.1 容器网络模型(CNM)
CNM是设计标准,定义了3个基本要素:沙盒(Sandbox)
,终端(Endpoint)
,网络(Network)
以太网接口
,端口
,路由表
,DNS配置
;1.2 Libnetwork
Libnetwork是标准的实现,除了实现了CNM中的3个基本要素外,还实现了本地服务发现(Service Discovery)
,基于Ingress的容器负载均衡
,网络控制层和管理层功能
。
1.3 驱动
如果说Libnetwork实现了控制层和管理层,那么驱动就负责实现数据层
。
Docker封装了若干内置驱动,通常被称为原生驱动或者本地驱动。在Linux中包括Bridge
,Overlay
,Macvlan
,在Windows中包括NAT
,Overlay
,Transport
,L2 Bridge
。
除了以上内置驱动,第三方也可以编写Docker网络驱动,这些驱动叫做远程驱动,例如Calico
,Contiv
,Kuryr
,Weave
。
Libnetwork支持同时激活多个网络驱动
1.4 Docker网络命令
命令 | 作用 |
---|---|
docker network ls | 列出运行在本地Docker主机上的全部网络 |
docker network create | 创建新的Docker网络,默认情况下,Windows会使用NAT,Linux会使用Bridge,可以使用 -d 指定驱动 |
docker network inspect | 提供Docker主机的详细配置信息 |
docker network prune | 删除Docker主机上全部未使用的网络 |
docker network rm | 删除Docker主机上指定的网络 |
是最简单的Docker网络,有以下特点:
每个Docker主机都有一个默认的单机桥接网络,在Linux上网络名称为Bridge,在windows上叫做nat,默认情况下,新创建的容器都会连接到该网络。除非创建容器时指定参数--network
。
使用docker network inspect
可以查看网络更加详细的信息
[root@huanzi-001 ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "302c36bc3cf1b9f7d1d2bc87f34f3fbc56f617add92e83729b9e9b467d3c2c7a",
"Created": "2020-02-04T10:10:35.753930939+08:00",
"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": {}
}
]
[root@huanzi-001 ~]#
创建网络
使用docker network create
创建一个新的单机桥接网络
[root@huanzi-001 ~]# docker network create lovehuanzi
d302c895b45591b8262fd0afcf306afe3a0d11b1498479c2f15c77a8e8793ac7
[root@huanzi-001 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
302c36bc3cf1 bridge bridge local
ac57c15024c7 docker_gwbridge bridge local
e863472805b3 host host local
7d6iv5ilwbcn ingress overlay swarm
d302c895b455 lovehuanzi bridge local
eefd134326c4 none null local
Linux上默认的Bridge网络是不支持通过Docker DNS服务进行域名解析的,自定义桥接网络可以
端口映射
实现覆盖网络适用于多机环境,允许单个网络包含多个Docker主机,这样不同Docker主机上的容器间就可以实现通信。
使用docker network create --d overlay
命令创建覆盖网络
root@huanzi-001 ~]# docker network create -d overlay huanzi-net
ojt9cxg2qsxegjcgu6ktoo2rs
[root@huanzi-001 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
302c36bc3cf1 bridge bridge local
ac57c15024c7 docker_gwbridge bridge local
e863472805b3 host host local
ojt9cxg2qsxe huanzi-net overlay swarm
7d6iv5ilwbcn ingress overlay swarm
d302c895b455 lovehuanzi bridge local
eefd134326c4 none null local
[root@huanzi-001 ~]#
[root@huanzi-002 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3afb6544913b bridge bridge local
72f048c911f2 docker_gwbridge bridge local
83491c86f3ab host host local
7d6iv5ilwbcn ingress overlay swarm
31762b86ae64 none null local
[root@huanzi-002 ~]#
在工作节点上执行docker network ls
发现看不见huanzi-net这个覆盖网络,因为只有当运行中的容器连接到了覆盖网络时,该网络才变为可用状态。
能看见ingress是因为在工作节点上运行有副本,该副本连接的是ingress,而huanzi-net是刚刚创建的,还没有副本,我们给huanzi-net分配副本之后再看一下。
[root@huanzi-001 ~]# docker service create --name huanzi-nginx --network huanzi-net --replicas 2 nginx:latest
yqkuakn91ieeo7ed01ftyyjsk
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
[root@huanzi-001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
yqkuakn91iee huanzi-nginx replicated 2/2 nginx:latest
ipvnc10w8l9h my-nginx replicated 5/5 nginx:latest *:8080->80/tcp
[root@huanzi-001 ~]#
[root@huanzi-002 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3afb6544913b bridge bridge local
72f048c911f2 docker_gwbridge bridge local
83491c86f3ab host host local
ojt9cxg2qsxe huanzi-net overlay swarm
7d6iv5ilwbcn ingress overlay swarm
31762b86ae64 none null local
[root@huanzi-002 ~]#
如何查看Docker容器的IP
[root@huanzi-001 ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4eae732468cc nginx:latest "nginx -g 'daemon of…" 21 minutes ago Up 21 minutes 80/tcp huanzi-nginx.2.s6fwv5gbuopzssbymyspu81ex
[root@huanzi-001 ~]#
拿到ID是4eae732468cc
[root@huanzi-001 ~]# docker container inspect 4eae732468cc
<...>
"NetworkSettings": {
<...>
"Networks": {
"huanzi-net": {
<...>
"IPAddress": "10.0.1.4",
<...>
}
}
}
}
]
IP地址是10.0.1.4
,属于覆盖网络的Subnet中。
覆盖网络的Subnet查看
[root@huanzi-001 ~]# docker network inspect huanzi-net
[
{
"Name": "huanzi-net",
"Id": "ojt9cxg2qsxegjcgu6ktoo2rs",
"Created": "2020-02-04T19:50:37.95254094+08:00",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.1.0/24",
"Gateway": "10.0.1.1"
}
]
},
<...>
可以看到,"Subnet": "10.0.1.0/24"
Docker内置的Macvlan
驱动可以实现,让容器化的应用,能够连接到外部物理网络上与之进行通信。通过为容器提供Mac和IP地址,让容器在外部物理网络上成为"公民"。
优点
是性能优异,无须端口映射或者额外桥接,可以直接通过主机接口访问容器接口。缺点
是需要将主机网卡设置为混杂模式,在大部分公有云平台上是不允许的。Macvlan适用于公司内部的数据中心网络环境,但在公有云上并不可行
创建一个macvlan100网络以及eth0.100子接口。
docker network create -d macvlan --subnet=10.0.0.0/24 --ip-range=10.0.0.0/25 --gateway=10.0.0.1 -o parent=eth0.100 macvlan100
部署容器至macvlan网络中
docker container run -d --name mactainer1 --network macvlan100 alpine sleep 1d
部署完成后,mactainer1容器可以ping通任何加入物理网络VLAN100的系统,并进行通信。
同一Docker主机上可以创建多个Macvlan网络
服务发现(Service Discovery)允许容器和Swarm服务通过名称互相定位。唯一的要求就是需要处于同一网络中。
--name
参数的Swarm服务或者独立的容器,都会将自己的名称和IP注册到Docker DNS服务举个例子,容器 c1 与容器 c2 位于相同的网络之中,c1 通过名称ping 容器 c2。
Docker DNS服务器中记录了全部容器名称和IP地址的映射关系
,Docker DNS服务器可以解析出c2对应的IP地址,并且将解析出的IP地址,返回给c1的本地DNS服务器,再进行ping操作。如果两个容器位于不同的网络之中,则 Dcoker DNS 服务器中也没有对方的映射记录,两者无法互相解析
Swarm支持两种服务发布模式,两种模式均保证服务从集群外可访问
区别:
-p
或--publish
发布服务时都是Ingress模式,如果需要使用Host模式,需要使用-publish
参数的完整格式,并且必须
加上mode=host
Host模式例子(逗号前后不允许有空格):
docker service create -d --name svc1 --publish published=5000,target=80,mode=host nginx
Ingress模式特点: