0%

Docker 中 4 种网络模型的概念和实现

关于 Docker 系列其他文章的传送门

  1. 《 简单了解 Linux 容器是什么 以及 Docker 常用命令操作说明 》

  2. 《 Docker 中 4 种网络模型的概念和实现 》     您当前所在位置

  3. 《 关于 Docker 中镜像与存储卷的概念和详细使用方法 》

  4. 《 使用 Dockerfile 定制镜像 搭建 php 站点 》

  5. 《 使用 Harbor 创建本地 Docker 仓库 》



Docker 网络

network

虚拟网络分类

首先,回顾一下虚拟化中的四种网络类型。

类型 描述
隔离桥 内部网络完全封闭,只能内部通信
仅主机桥 在隔离的基础上,仅能和宿主机通信
路由桥 内网主机可以通过路由把报文转发出去,但是如果外部没有对应的路由,报文是回不来的
NAT 桥 内网主机报文通过 NAT 桥上的网关地址转发出去,回来时再通过 连接追踪 机制转发给内网主机

这篇《 一篇文章讲解什么是虚拟化和 kvm 的使用方法 》详细描述了各种网络模型的实现方法

Docker 中的网络分类

Docker 中也有四种网络,但是 Docker 中的网络使用了 Linux Bridgenamespace 机制,类似于虚拟化中的网络,但又不完全一样

这里说明 Docker 的网络分类和使用方法

类型 描述
桥网络 类似虚拟机中的网桥,默认是 docker(NAT)
共享桥网络 将 6 种名称空间内的 UTS、IPC、Network 共享,但是其他 3 个依然独立,也称之为 联盟式网络,这样在共享桥内的网络就像在同一台主机运行一样,但是 Mount、User 和 PID 依然独立
共享宿主机网络 容器直接使用宿主机的根网络名称空间,宿主机能看到网络信息,容器内也都可以看到
none 网络 无网络,就好像没有网卡的计算机设备

这张图展现了 4 种 Docker 网络的区别
network

四种网络的使用方法

第 1 种 桥网络

创建容器 node1 并指定使用

1
2
3
4
5
6
7
8
9
docker container run --name node1 --rm -it --network bridge centos:7
# --rm 停止即删除 # 指定网络使用 bridge,也是默认

# 查看 ip 等信息,可以看到 ip 地址为 172.17.0.2/16
[root@aec511c03380 /] ip a show eth0
63: eth0@if64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

第 2 种 共享桥网络

再创建一个容器 node2,并指定使用 node1 的网络

1
2
3
4
5
6
7
8
9
docker container run --name node2 --rm -it --network container:node1 centos:7
# 这里把网络指向了第一个容器的网络

# 查看 node2 的 ip 等信息,发现不仅 ip 地址和 node1 一样,连 mac 和主机名都一样。但是文件、进程等都是隔离的
[root@aec511c03380 /] ip a show eth0
63: eth0@if64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

第 3 种 共享宿主机网络

创建一个 node3,并指定使用宿主机的命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
docker container run --name node3 --rm -it --network host centos:7
# 这里指定网络类型为 host

# 查看 node3 的 ip 等信息,发现所有网卡、主机名等信息都和宿主机一毛一样了,但是文件、进程依旧都是隔离的
[root@docker /] ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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 master br-ex state UP group default qlen 1000
link/ether 00:0c:29:cf:e7:f6 brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:22:ce:de:82 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:22ff:fece:de82/64 scope link
valid_lft forever preferred_lft forever
36: br-ex: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:cf:e7:f6 brd ff:ff:ff:ff:ff:ff
inet 192.168.50.11/24 brd 192.168.50.255 scope global noprefixroute br-ex
valid_lft forever preferred_lft forever
inet6 fe80::b052:84ff:fe4c:df5c/64 scope link
valid_lft forever preferred_lft forever
64: veth98cb889@if63: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 3e:f0:a6:03:15:27 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::3cf0:a6ff:fe03:1527/64 scope link
valid_lft forever preferred_lft forever

第 4 种 none 网络

也就等于设备没有网卡

1
2
3
4
5
6
7
8
9
docker container run --name node3 --rm -it --network none centos:7
# 指定网络为 none

# 查看 ip 等信息发现,只有一个回环地址
[root@d98998a4e071 /] ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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

注入网络类信息

常用的网络注入选项,建议使用 docker network --help 查看帮助信息

容器类命令中的网络参数

1
2
3
4
5
6
7
8
docker
container: ###### 容器类命令 ######
run # 创建+启动
-h # 指定容器的主机名 = --hostname
--add-host # 注入解析到 hosts 文件
--dns # 注入 dns 地址
--dns-search # 注入搜索域
-p # 定制对外暴露的方式 (DNAT)

1. 创建容器

1
2
3
4
5
6
docker run --name node1 -it      \
-h node1.template.com \ # 注入主机名为 node1
--add-host www.template.com:192.168.1.1 \ # 注入一条解析到 /etc/hosts 下
--dns 114.114.114.114 \ # 指定 dns 服务器 ip
--dns-search template.com \ # 指定 dns 搜索域
centos # 使用 centos 镜像

2. 查看

可以看到主机名已经注入了 node1,再查看 hosts 信息,也已经有了我们指定的解析 "192.168.1.1 www.template.com"

1
2
3
4
[root@node1 /] cat /etc/hosts
127.0.0.1 localhost
192.168.1.1 www.template.com
172.17.0.2 node1.template.com node1

查看 DNS 信息,看到指定的 search 和 nameserver 都应设置成功了。

1
2
3
[root@node1 /] cat /etc/resolv.conf
search template.com
nameserver 114.114.114.114

常用的网络类注入就搞定了,简单吧!

创建 Docker 网络

如果不想使用默认的网络,也可以自己创建 Docker 网络。

网络类参数

1
2
3
4
5
6
7
8
9
10
docker
network: ###### 网络类选项 ######
ls # 显示当前的网络信息
create # 创建网络
-d # 驱动 默认 bridge
--subnet # 指定子网,默认第一个地址是网关
--gateway # 指定网关
--ip-range # 设定 ip 地址范围
connect # 把指定的网络(接口)连接到容器
disconnet # 从容器拆除指定的网络(接口)

1.创建网络

1
2
3
4
5
6
docker network create \             # 创建一个叫 mybr0 的网络
-d bridge \ # 指定网络类型为 bridge
--subnet 10.10.0.0/16 \ # 指定子网范围
--gateway 10.10.10.1 \ # 指定网关,默认为可用地址的第一个
--ip-range 10.10.50.0/24 \ # 设定 ip 范围,默认为全部可用 ip 地址
mybr0 # 网络名字为 mybr0

2.启动一个容器

指定使用刚才创建的 mybr0 网络

1
docker container run --name node1 --rm -it --network mybr0 centos

3.查看

进入容器查看获取到的 ip,就是刚才创建的 mybr0 中的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@0fe7b88ec7ff /] ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
172: eth0@if173: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:0a:0a:32:00 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.10.50.0/16 brd 10.10.255.255 scope global eth0
valid_lft forever preferred_lft forever

[root@0fe7b88ec7ff /] ip route
default via 10.10.10.1 dev eth0
10.10.0.0/16 dev eth0 proto kernel scope link src 10.10.50.0

如果想给容器添加一个网络(接口),可以这样使用

1
2
docker network connect mybr0 node1   # 给容器添加一个 mybr0 网络 (接口)
docker network disconnect mybr0 node1 # 将 mybr0 网络 (接口) 从容器拆除

开放入站通信

如果容器内部运行了一个服务,想要对外开放,可以把端口映射到宿主机上,方法是在启动容器时,加入 -p 选项指定映射方式

-p 选项的使用格式

(1). -p <containerPort> 将容器的指定端口,映射至主机所有地址的一个动态端口

1
docker run -p 80 nginx

(2). -p <hostPort>:<containerPort> 将容器的指定端口,映射至主机的指定端口

1
docker run -p 10080:80 nginx

(3). -p <ip>::<containerPort> 将容器指定的端口,映射至主机指定的动态端口

1
docker run -p 192.168.50.11::80 nginx

(4). -p <ip>:<hostPort>:<containerPort> 将容器的指定端口,映射至主机指定的 ip 和指定的端口

1
docker run -p 192.168.50.11:10080:80 nginx

查看指定容器的端口映射关系:

1
2
3
4
docker port <CONTAINER_NAME>

~ ] docker port nginx
80/tcp -> 0.0.0.0:80