学校网站建设必要性百度精准搜索
在当前万物互联的时代下,网络成为必不可少的基础设施,Docker在网络功能上也非常完善,通过命令和参数轻松的为容器制定不同的网络方案。
一、容器网络
容器网络实质上也是由Docker为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP协议栈、端口套接字、IP路由表、防火墙等等与网络相关的模块。

Docker网络中有三个核心概念:沙盒(Sandbox)、网络(Network)、端点(Endpoint)。
- 沙盒,提供了容器的虚拟网络栈,也即端口套接字、IP路由表、防火墙等内容。隔离容器网络与宿主机网络,形成了完全独立的容器网络环境。
- 网络,可以理解为Docker内部的虚拟子网,网络内的参与者相互可见并能够进行通讯。Docker的虚拟网络和宿主机网络是存在隔离关系的,其目的主要是形成容器间的安全通讯环境。
- 端点,位于容器或网络隔离墙之上的洞,主要目的是形成一个可以控制的突破封闭的网络环境的出入口。当容器的端点与网络的端点形成配对后,就如同在这两者之间搭建了桥梁,便能够进行数据传输了。
这三者形成Docker网络核心模型,也就是容器网络模型(Container Network Model)。
二、Docker的网络实现
容器网络模型为容器引擎提供了一套标准的网络对接范式,Docker中,实现这套范式的是Docker所封装的libnetwork模块。
Docker官方提供了五种Docker网络驱动,分别是:Bridge Driver、Host Driver、Overlay Driver、MacLan Driver、None Driver。Bridge和 Overlay在开发中使用频率较高。

- Bridge,Docker容器的默认网络驱动,通过网桥来实现网络通讯。
- Overlay,借助Docker集群模块Docker Swarm搭建的跨Docker Daemon网络。通过它可以搭建跨物理主机的虚拟网络,进而让不同物理机中运行的容器感知不到多个物理机的存在。
关于Docker的网络实现还有非常多的细节,但是对于开发者来说,只是使用Docker,这里就不做过多总结。
在安装Docker时,会自动安装一块Docker网卡称为docker0,用于Docker各容器及宿主机的网络通信,网段为172.0.0.1。
ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255ether 02:42:aa:ea:de:cc txqueuelen 0 (Ethernet)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
三、容器互联
Docker提倡容器与应用共生的轻量级容器理念,所以容器中通常只包含一种应用程序,但如今纷繁的互联网应用,都是多系统多结点。举例,Web应用,需要业务应用、数据库应用、缓存应用等组成。在Docker里需要通过多个容器来组成这样的系统。而互联网时代的应用,组件间的通讯方式主要以网络为主,所以打通容器间的网络,是使它们能够互相通讯的关键所在。
要让一个容器连接到另外一个容器,可以在容器通过docker create或docker run创建时通过--link选项进行配置。
例如,创建一个MySQL容器,将运行Web应用的容器连接到这个MySQL容器上,打通两个容器间的网络,实现它们之间的网络互通。
docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
docker run -d --name webapp --link mysql webapp:latest
容器间的网络已经打通,Docker为容器间连接提供了非常友好的方式,只需要将容器的网络命名填入到连接地址中,就可以访问需要连接的容器了。假设在Web应用中使用JDBC进行数据库连接。
String url = "jdbc:mysql://mysql:3306/webapp";
连接地址中的mysql类似域名解析,Docker会将其指向MySQL容器的IP地址。Docker在容器互通中不再需要真实的知道另外一个容器的IP地址就能进行连接。
具体来对比,在以往的开发中,每切换一个环境(例如将程序从开发环境提交到测试环境),都需要重新配置程序中的各项连接地址等参数,而在Docker里,并不需要关心这个,只需要程序中配置被连接容器的别名,映射IP的工作就交给Docker完成了。
四、暴露端口
虽然容器间的网络打通了,但并不意味着可以任意访问被连接容器中的任何服务。Docker为容器网络增加了一套安全机制,只有容器自身允许的端口,才能被其他容器所访问。
容器自我标记端口可被访问的过程,通常称为暴露端口。docker ps的结果中可以看到容器暴露给其他容器访问的端口,连接到容器后,只能对这开放端口进行访问。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7da13d7fc93 redis "docker-entrypoint.s…" 21 hours ago Up 21 hours 6379/tcp redis
71d09fd4bd9e nginx "nginx -g 'daemon of…" 21 hours ago Up 21 hours 80/tcp zealous_wu
端口的暴露可以通过Docker镜像进行定义,也可以在容器创建时进行定义。在容器创建时进行定义的方法是借助--expose选项。
docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 13306 --expose 23306 mysql:5.7
为MySQL暴露13306和23306两个端口,暴露后可以通过docker ps中看到这两个端口已经成功的打开。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c4e645f21d7 mysql:5.7 "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 3306/tcp, 13306/tcp, 23306/tcp, 33060/tcp mysql
容器暴露了端口只是类似打开了容器的防火墙,具体能不能通过这个端口访问容器中的服务,还需要容器中的应用监听并处理来自这个端口的请求。
五、管理网络
容器能够互相连接的前提是两者同处于一个网络中。网络这个概念可以理解为Docker所虚拟的子网,而容器网络沙盒可以看做是虚拟的主机,只有当多个主机在同一子网里时,才能相互通信。
启动Docker服务时,它会创建一个默认的bridge网络,创建的容器在不专门指定网络的情况下都会连接到这个网络上。所以能够把WebApp容器连接到MySQL容器上。
通过docker inspect命令查看容器,可以在Network部分看到容器网络相关的信息。
docker inspect redis{"Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "82d8396ce6588626a708e044bae484446dc74e5904c34b7556a86ead8360ce56","EndpointID": "fb02888475fb55eb3d60b3f5af0a4b6eab2bb41b24af6c043f0555e727eaa104","Gateway": "172.17.0.1","IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:03","DriverOpts": null}}
}
可以看到redis容器在bridge网络中所分配的IP地址,端口、Mac地址,网关地址等信息Docker默认创建的bridge网络非常重要的,在没有明确指定容器网络时,容器都会连接到这个网络中。
六、创建网络
Docker也能够创建网络,形成自定义虚拟子网。
docker CLI里与网络相关的命令都以docker network开头,创建网络的命令是docker network create。
docker network create -d bridge individual
通过-d选项可以为新的网络指定驱动的类型,其值可以是前文提到的五种类型,bridge、host、overlay、maclan、none,也可以是其他网络驱动插件所定义的类型。这里指定了Bridge Driver(不指定网络驱动时,Docker也会默认采用Bridge Driver作为网络驱动)。
通过docker network ls或是docker network list可以查看Docker 中已经存在的网络。
docker network list
NETWORK ID NAME DRIVER SCOPE
82d8396ce658 bridge bridge local
5dcf2c5536f1 host host local
765cc3ce6414 individual bridge local
c1a9c0eeae68 none null local
之后在创建容器时,可以通过--network来指定容器所加入的网络。
docker run -d --name ng --network individual nginx
我们通过 docker inspect
观察一下此时的容器网络。
docker inspect ng{"Networks": {"individual": {"IPAMConfig": null,"Links": null,"Aliases": ["936e3b4650a3"],"NetworkID": "765cc3ce64142e485f082fdacad12ea64647f3f9483cc833ebbc355d564c0d9b","EndpointID": "654843248c877a8e840bd7aac99ef66b1b30d71274b483fda859c807f7493929","Gateway": "172.18.0.1","IPAddress": "172.18.0.2","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:12:00:02","DriverOpts": null}}
}
可以看到,容器所加入网络已经变成了individual。
通过--link让处于另外一个网络的容器连接到这个容器上,结果不能正常启动,Docker提醒两个容器处于不同的网络,之间不能相互连接引用。
通过--network,可以修改加入的网络,修改为individual就可以成功建立容器间的网络连接了。
docker run -d --name webapp --link mysql --network individual webapp:latest
七、端口映射
以上都是容器直接通过Docker网络进行的访问,在实际应用中,还有一个常见的需求,需要在容器外通过网络访问容器中的应用。在Docker中,提供了一个端口映射的功能实现这样的需求。

通过Docker端口映射功能,可以把容器的端口映射到宿主操作系统的端口上,当从外部访问宿主操作系统的端口时,数据请求就会自动发送给与之关联的容器端口。
映射端口,可以在创建容器时使用-p或--publish选项。
docker run -d --name nginx -p 80:80 -p 443:443 nginx
使用端口映射选项的格式是-p <ip>:<host-port>:<container-port>
,其中ip是宿主操作系统的监听ip,可以用来控制监听的网卡,默认为0.0.0.0监听所有网卡。host-port和container-port分别表示映射到宿主操作系统的端口和容器的端口,这两者是可以不一样的,可以将容器的80端口映射到宿主操作系统的8080端口,传入-p 8080:80
即可。
可以在容器列表里看到端口映射的配置。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
750d2a872d17 nginx "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
d7da13d7fc93 redis "docker-entrypoint.s…" 22 hours ago Up 22 hours 6379/tcp redis
通过同网段其他机器访问宿主机80端口,宿主机会将请求转发到Docker容器内。
curl 10.255.242.168:80<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
参考:
http://blog.poetries.top/2018/11/20/docker-base/