Docker架构简介

铺垫 ——容器与虚拟机

虚拟机

一般常用的传统虚拟机如 VMware , VirtualBox 之类的需要模拟整台机器包括硬件。

每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。

每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。

容器

容器技术是和宿主机共享硬件资源及操作系统,可以实现资源的动态分配。

容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。

简单来说的话就是 ——容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。

07.png

08.png

  • 容器是一个应用层抽象,用于将代码和依赖资源打包在一起。 多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动 。

  • 虚拟机(VM)是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个VM在一台机器上运行。每个VM都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且VM启动也十分缓慢 。

使用场景的区别:

虚拟机更擅长于彻底隔离整个运行环境。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而容器通常用于隔离不同的应用 ,例如前端,后端以及数据库。

那什么是Docker?

Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。Docke最初实现是基于LXC。

而 LXC 是 Linux 发展出的另一种虚拟化技术,简单来讲, LXC不是模拟一个完整的操作系统,而是对进程进行隔离,相当于是在正常进程的外面套了一个保护层。

对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。

三个概念
  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

10.jpg

Image(镜像)

Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像不包含任何动态数据,其内容在构建之后也不会被改变。

Docker设计时,就充分利用Union FS的技术,将其设计为分层存储的架构。 镜像实际是由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。

容器(Container)——镜像运行时的实体

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

实际上,容器 = 镜像 + 读写层。

Repository(仓库)

Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。

但是, 如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。

有时候会把仓库(Repository)和仓库注册服务器(Registry)混为一谈,并不严格区分。

Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。

实际上,一个 Docker Registry 中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应着一个镜像。

所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。

我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 Latest 作为默认标签。

仓库又可以分为两种形式:

  • Public(公有仓库)
  • Private(私有仓库)

Docker Registry 公有仓库是开放给用户使用、允许用户管理镜像的 Registry 服务。

一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。

当用户创建了自己的镜像之后就可以使用 Push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 Pull 下来就可以了。

Docker架构图示

img

Docker 使用 C/S 结构,即客户端/服务器体系结构。Docker 客户端与 Docker 服务器进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。

Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTful 、 Stock 或网络接口与远程 Docker 服务端进行通信。

Docker Client

Docker Client是Docker架构中用户用来和Docker Daemon建立通信的客户端。用户使用的可执行文件为docker,通过docker命令行工具可以发起众多管理container的请求。

Docker Client发送容器管理请求后,由Docker Daemon接受并处理请求,当Docker Client接收到返回的请求相应并简单处理后,Docker Client一次完整的生命周期就结束了。当需要继续发送容器管理请求时,用户必须再次通过docker可执行文件创建Docker Client。

Docker Daemon

Docker Daemon是Docker架构中一个常驻在后台的系统进程,功能是:接受并处理Docker Client发送的请求。该守护进程在后台启动了一个Server,Server负责接受Docker Client发送的请求;接受请求后,Server通过路由与分发调度,找到相应的Handler来执行请求。

(详细架构以后有机会再说)

Docker的特点和优点

  • 轻量,在一台机器上运行的多个Docker容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。
  • 标准,Docker容器基于开放式标准,能够在所有主流Linux版本、Microsoft Windows以及包括VM、裸机服务器和云在内的任何基础设施上运行。
  • 安全,Docker赋予应用的隔离性不仅限于彼此隔离,还独立于底层的基础设施。Docker默认提供最强的隔离,因此应用出现问题,也只是单个容器的问题,而不会波及到整台机器。

  • Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“这段代码在我机器上没问题啊”这类问题;——一致的运行环境

  • 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间

  • 避免公用的服务器,资源会容易受到其他用户的影响。——隔离性

  • 善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展

  • 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便

  • 使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署

Dockerfile

前面我们已经提到了 Docker 的一些基本概念。以 CTF 的角度来看,我们可以去使用 Dockerfile 定义镜像,依赖镜像来运行容器,可以去模拟出一个真实的漏洞场景。

Dockerfile 是自动构建 Docker 镜像的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 Linux 下的 Shell 命令。