19.1 命名空间隔离的安全

Docker容器和LXC容器在实现上很相似,所提供的安全特性也基本一致。当用docker run命令启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。

命名空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在本地主机上的进程和其他容器通过正常渠道发现和影响。

例如,通过命名空间机制,每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的套接字(socket)或接口。当然,容器默认可以与本地主机网络连通,如果主机系统上做了相应的交换设置,容器可以像跟主机交互一样和其他容器交互。启动容器时,指定公共端口或使用连接系统,容器可以相互通信了(用户可以根据配置来限制通信的策略)。

从网络架构的角度来看,所有的容器实际上是通过本地主机的网桥接口(docker0)进行相互通信,就像物理机器通过物理交换机通信一样。

那么,Linux内核中实现命名空间(特别是网络命名空间)的机制是否足够成熟呢?

Linux内核从2.6.15版本(2008年7月发布)开始引入命名空间,至今经历了数年的演化和改进,并应用于诸多大型生产系统中。

实际上,命名空间的想法和设计提出的时间要更早,最初是OpenVZ项目的重要特性。OpenVZ项目早在2005年就已经正式发布,其设计和实现更加成熟。

当然,与虚拟机方式相比,通过命名空间来实现的隔离并不是那么绝对。运行在容器中的应用可以直接访问系统内核和部分系统文件。因此,用户必须保证容器中应用是安全可信的(这跟保证运行在系统中的软件是可信的一样),否则本地系统将可能受到威胁,即必须保证镜像的来源和自身可靠。

Docker自1.3.0版本起对镜像管理引入了签名系统,加强了对镜像安全性的防护,用户可以通过签名来验证镜像的完整性和正确性。