docker 系列:底层知识

简介: Docker 采用的是 **C/S 架构**,使用 REST API、UNIX 套接字或网络接口进行通信。一般客户端会和 Docker 服务运行在同一台机子上,像我们平常使用的 docker build、pull、run 等命令就是发送到本地客户端上的,本地客户端再发送给 Docker 服务端。另外,客户端也可以独立部署,像 Docker Compose。

总体架构

Docker 采用的是 C/S 架构,使用 REST API、UNIX 套接字或网络接口进行通信。一般客户端会和 Docker 服务运行在同一台机子上,像我们平常使用的 docker build、pull、run 等命令就是发送到本地客户端上的,本地客户端再发送给 Docker 服务端。另外,客户端也可以独立部署,像 Docker Compose。

Docker 服务一般是以守护进程的形式运行,它会监听客户端的请求,并且进行容器的构建、运行和分发,下面即 Docker 的总体架构

docker 架构

  • Docker 守护进程:侦听 Docker API 请求并管理 Docker 对象,例如镜像、容器、网络和卷。守护进程还可以与其他守护进程通信以管理 Docker 服务。
  • Docker 客户端:通过 Docker API 发送命令给 Docker 守护进程(dockerd),让守护进程执行对应的命令动作,例如发送 docker run 命令。
  • Docker Registry:存储了 Docker 镜像。像 Docker Hub 就是一个任何人都可以使用的公共注册中心,Docker 会默认地从 Docker Hub 上查找镜像。当然,我们也可以自己搭建个 Docker Registry。

容器的演变

一开始,Docker 是基于 Linux 内核提供的技术进行容器管理的,它将 Linux 复杂的容器管理进行了简化,形成了自己独有的一套命令体系。后来,Docker 将底层技术进行了抽象,定义了一组接口,只要实现了这组接口,那么就可以进行容器的管理,这就是 Libcontainer

随着 Docker 的火热,越来越多的公司加入容器技术的开发,在 2015 年谷歌、微软、Docker 等公司成立了 OCI 组织,致力于定制一致的容器标准。在 Libcontainer 的基础上推出了容器引擎: runC

可能大家会比较好奇的是 windows 的容器架构又是怎么样的?其实在 windows 上也抽象出来了 CGroupNamespace,它也是符合 OCI 容器标准的,如下图:

容器之windows

容器之Linux

(图片来自 Black Belt 在 DockerCon 的演讲:Docker 与 Windows 容器揭秘

底层技术

Docker 是用 Go 语言编写的,所以天生就支持这种跨平台的部署。不过主流的服务器都是 Linux 系统,所以我们来看看关于 Linux 的容器底层技术:Namespaces(资源隔离)CGroups (资源限制)UnionFS (镜像和容器分层)

Namespaces(资源隔离)

Namespaces 是 Linux 内核在 2.4.19 版本后陆续引入的概念,它将系统的全局资源通过抽象划分,使得在同一 namespace 中的进程看起来拥有自己的全局资源。当前 Linux 支持以下六种 Namespace

namespace 隔离的系统资源
Mount namespaces 文件系统挂接点
IPC namespaces 特定的进程间通信资源
UTS namespaces nodename 和 domainname
PID namespaces 进程 ID
Network namespaces 网络相关的系统资源
User namespaces 用户和组 ID 空间

我们可以看到有 Network 网络的,也有用户 User 的 隔离。当容器被创建时,会创建上面对应的 Namespace 实例,然后将容器进程划分到此 Namespace 里,以此实现了隔离功能。

CGroups(资源限制)

上面的 Namespace 为我们提供了环境隔离的功能,但这还远远不够,因为各个进程所使用的资源还是没有限制的,比如 CPU、内存等。一旦某个容器超过上限,则有可能会被 kill。因此,对资源的限制使用就很重要了,而 Linux 内核的 CGroups 就提供了此功能。

当我们创建了一个容器时,默认的会在 /sys/fs/cgroup 目录下生成对应的资源使用目录,比如 docker run nginx:test,则会在 /sys/fs/cgroup/memory/docker/nginx容器ID 目录下有对应的资源描述文件:

资源限制

使用命令 docker run --memory 1024M nginx:test时,就可以进行内存资源的限制了。其他资源限制命令也类似。

UnionFS(镜像和容器分层)

Linux 的 UnionFS (联合文件系统) 技术是用来将不同物理位置的目录合并挂载到同一个目录中。实际上 UnionFS 在不同的系统上有不同的实现,现在主流的是 AUFS、Devicemapper 和 OverlayFS。在 Docker 中最常用的是 AUFS,我们主要来看看 AUFS 的相关知识。

首先,默认情况下 AUFS 有个特点,就是要联合的第一个文件是可读可写的,后面的文件目录则只能只读。例如,我们将 teacher、student 目录联合到 mnt 目录下:

# 将 teacher 和 student 联合到 mnt
sudo mount -t aufs -o dirs=./teacher:./student none ./mnt

├── teacher
│   ├── A
│   └── C
└── student
    ├── B
    └── C

# 查看./mnt
$ tree ./mnt

├── A
├── B
└── C

当我们对 mnt 下的 C 目录修改后,会在 teacher 目录下同步看到修改,但 student 目录就不会被修改了,因为它是只读的。那这样的机制在 Docker 里有什么作用呢?

首先,Docker 将文件系统分为容器层和镜像层,这里的容器层相当于上面的 teacher 目录,镜像层相当于 student 目录。也就是容器层文件是可读可写,而镜像层是只读的。这样的话,有利于多个容器共享一个镜像文件。

而且 Docker 在一开始的时候并不会创建容器层,而是先使用镜像层文件,只有当容器里的文件发生了修改,此时才会真正的创建出可读可写的容器层,以保证不影响镜像层文件。而这种类似写时复制技术,为系统节省了很多不必要的存储文件。

Docker 的安全

在审查 Docker 的安全性时,主要从下面四个方面考虑:

(一)Namespaces、CGroups 的安全

Docker 容器与 LXC 容器非常相似,它们具有一样的安全特性。Namespaces 提供了第一种也是最直接的隔离形式,使得在容器内运行的进程无法看到在另一个容器或主机系统中运行的进程。每个容器也有属于自己的网络堆栈,这意味着一个容器不能获得对另一个容器的套接字或接口的特权访问。

CGroups 是 Linux 容器的另一个关键组件,能对资源进行核算和限制,提供了许多有效指标,确保每个容器获得公平的资源使用(例如内存、CPU、磁盘 I/O),使得单个容器无法耗尽系统资源。这在多租户平台(例如 PaaS)上尤为重要,能保证用户一致的正常运行性能。

(二)Docker 守护进程的安全性

运行 Docker 守护进程是需要 root 特权的,因此只有受信任的 User 才能运行 Docker 守护进程。但是由于 Docker 是允许主机和容器共享文件夹的,如果我们将系统文件映射到 Docker 容器里,那肯定也是能突破系统防护的。不过,这主要取决于我们关联的主机文件,一般还比较好控制。

Docker 也需要防止某些非法请求创建了破坏性的容器。在 0.5.2 之后为了防止一些恶意用户的跨站脚本攻击,Docker 使用了本地的 UNIX 套接字而不是绑定在 127.0.0.1 上的 TCP 套接字,这样就允许用户进行本地权限检查,以进行安全访问了。

(三)Linux 内核的安全

默认情况下,Docker 启动的是一组功能受限的容器,这使得容器中的“root”比真正的“root”拥有更少的特权,例如:

  • 禁止任何挂载操作;
  • 禁止访问本地套接字(以防止数据包欺骗);
  • 禁止某些文件系统的操作,例更改文件所有者或属性;
  • 禁止模块加载;

这使得入侵者设法升级到容器内的 root,也很难以对主机造成严重性的破坏。

(四)其他内核安全特性

  • 允许配置只能拉取指定秘钥签名的镜像仓库
  • 使用 GRSEC 和 PAX 运行内核,在编译和运行时增加许多安全检查
  • 使用具备安全特性的容器模板
  • 自定义访问控制策略
相关文章
|
数据可视化 关系型数据库 MySQL
《docker从零到壹》相关系列 目录
《docker从零到壹》相关系列 目录
146 0
|
Ubuntu 数据中心 开发者
[Docker系列·0] Docker101
###Docker是什么 [翻译自 whatisdocker](https://www.docker.com/whatisdocker/) >Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications. Consisting of Docke
3674 1
|
程序员 虚拟化 Docker
Docker深入浅出系列——Docker简介
我是架构师张飞洪,钻进浩瀚代码,十年有余,人不堪其累,吾不改其乐。如果你和我的看法不一样,请关注我的头条号,我们一起奇闻共赏,疑义相析。 本节属于入门简介,从三个小方面进行简单介绍Docker。
1314 0
|
Shell Linux Docker
[Docker系列·1] Docker第一步
###安装Docker Docker支持很多种宿主操作系统(详见[installation](https://docs.docker.com/installation/ )),这里以CentOS为例,简述安装: Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装相应的EPEL包。 **6.5 yum安装** ```
2773 0
|
14天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
147 77
|
22天前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
15天前
|
数据建模 应用服务中间件 nginx
docker替换宿主与容器的映射端口和文件路径
通过正确配置 Docker 的端口和文件路径映射,可以有效地管理容器化应用程序,确保其高效运行和数据持久性。在生产环境中,动态替换映射配置有助于灵活应对各种需求变化。以上方法和步骤提供了一种可靠且易于操作的方案,帮助您轻松管理 Docker 容器的端口和路径映射。
59 3
|
22天前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
54 7
|
22天前
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
30 5
|
22天前
|
开发框架 安全 开发者
Docker 是一种容器化技术,支持开发者将应用及其依赖打包成容器,在不同平台运行而无需修改。
Docker 是一种容器化技术,支持开发者将应用及其依赖打包成容器,在不同平台运行而无需修改。本文探讨了 Docker 在多平台应用构建与部署中的作用,包括环境一致性、依赖管理、快速构建等优势,以及部署流程和注意事项,展示了 Docker 如何简化开发与部署过程,提高效率和可移植性。
49 4