【注意】最后更新于 May 22, 2019,文中内容可能已过时,请谨慎使用。
引言
docker 是一个非常方便的工具,在在使用过程中,需要使用一些网络相关的信息。找了一些资料,在这里做点笔记。
docker网络模式
docker网络有四种模式:桥模式、主机模式、容器模式和无网络模式。
bridge 模式网络
在桥模式中,Docker守护进程创建一个虚拟网卡,附加在其上的任何网卡之间都能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口放置在宿主机的命名空间中,从而将宿主机上的所有容器都连接到这个内部网络上。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。
1
2
3
4
5
6
|
$ docker run -d -P --net=bridge nginx:1.9.1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
17d447b7425d nginx:1.9.1 nginx -g 19 seconds ago
Up 18 seconds 0.0.0.0:49153->443/tcp, 0.0.0.0:49154->80/tcp trusting_feynman
|
因为bridge模式是Docker的默认设置,所以你也可以使用docker run -d -P nginx:1.9.1。如果你没有使用-P(发布该容器暴露的所有端口)或者-p
host_port:container_port(发布某个特定端口),IP数据包就不能从宿主机之外路由到容器中。
{% asset_img bridge-mode.png breige %}
host模式网络
该模式将禁用Docker容器的网络隔离。因为容器共享了宿主机的网络命名空间,直接暴露在公共网络中。因此,你需要通过端口映射(port mapping)来进行协调。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$ docker run -dit --rm -net=host --name=testnet centos:7
$ ip addr | grep -A 2 eth0:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:c6:38:28 brd ff:ff:ff:ff:ff:ff
inet 172.27.16.10/20 brd 172.27.31.255 scope global eth0
$ docker exec -it testnet bash
# apt-get update
# apt-get install iproute2
# ip addr | grep -A 2 eth0:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:c6:38:28 brd ff:ff:ff:ff:ff:ff
inet 172.27.16.10/20 brd 172.27.31.255 scope global eth0
|
我们可以从上例中看到:容器和宿主机具有相同的IP地址 172.27.16.10
在下图中,我们可以看到:当使用host模式网络时,容器实际上继承了宿主机的IP地址。该模式比bridge模式更快(因为没有路由开销),但是它将容器直接暴露在公共网络中,是有安全隐患的。
{% asset_img host-mode.png host %}
container模式网络
该模式会重用另一个容器的网络命名空间。通常来说,当你想要自定义网络栈时,该模式是很有用的。实际上,该模式也是Kubernetes使用的网络模式。
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
|
$ docker run -dit --rm --net=bridge --name=testnet ubuntu:16.04
$ docker exec -it testnet bash
# apt-get update
# apt-get install iproute2
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
290: eth0@if291: <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
$ docker run -dit --rm --net=container:testnet --name=testnet2 ubuntu:16.04
$ docker exec -it testnet2 bash
# apt-get update
# apt-get install iproute2
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
290: eth0@if291: <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
|
结果(上面的例子)显示:第二个容器使用了--net=container
参数,因此和第一个容器 testnet
具有相同的IP地址172.17.0.2
。
none模式网络
该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务);你希望自定义网络,在第3章中有很多选项使用了该模式。
使用固定IP
使用固定IP可以自己先创建一个 bridge
的网卡,然后启动的时候指定网卡和IP(默认的网卡不能指定IP启动)。
1
2
3
4
5
6
7
8
9
10
|
$ docker network create \
--driver=bridge \
--subnet=172.28.0.0/16 \
--ip-range=172.28.5.0/24 \
--gateway=172.28.5.254 \
br0
# subnet 创建子网 , ip-range IP地址池
# 172.28.0.0/16 地址范围是 172.28.0.1 到 172.28.255.254
# 172.28.5.0/24 地址范围是 172.28.5.1 到 172.28.5.254
|
可以通过站长工具 进行IP的计算
参考资料