Docker 三大核心概念

Docker 核心概念

 

镜像

镜像是什么呢?通俗地讲,它是一个只读的文件和文件夹组合。它包含了容器运行时所需要的所有基础文件和配置信息,是容器启动的基础。因此你想启动一个容器,那首先必须要有一个镜像。

镜像是 Docker 容器启动的先决条件。

 

如果你想要使用一个镜像,你可以用这两种方式:

1、自己创建镜像。

通常情况下,一个镜像是基于一个基础镜像构建的,你可以在基础镜像上添加一些用户自定义的内容。

例如:你可以基于centos镜像制作你自己的业务镜像,首先安装nginx服务,然后部署你的应用程序,最后做一些自定义配置,这样一个属于你自己的业务镜像就做好了。

 

2、从功能镜像仓库拉取别人制作好的镜像。

一些常用的软件或者系统都会有官方已经制作好的镜像。
例如:nginx、ubuntu、centos、mysql等,你可以到 Docker Hub 搜索并下载它们。

 

容器

容器是什么呢?
容器是 Docker 的另一个核心概念。通俗地讲,容器是镜像的运行实体。

镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。

容器有初建、运行、停止、暂停和删除五种状态。

 

虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。

 

仓库

Docker 的镜像仓库类似于代码仓库,用来存储和分发 Docker 镜像。镜像仓库分为公共镜像仓库和私有镜像仓库。

目前,Docker Hub(https://hub.docker.com/) 是 Docker 官方的公开镜像仓库,它不仅有很多应用或者操作系统的官方镜像,还有很多组织或者个人开发的镜像供我们免费存放、下载、研究和使用。除了公开镜像仓库,你也可以构建自己的私有镜像仓库。

镜像、容器、仓库,三者之间的联系,如下图所示:

图片

由上图可知,镜像是容器的基石,容器是由镜像创建的。一个镜像可以创建多个容器,容器是镜像运行的实体。仓库是用来存放和分发镜像的。

 

Docker 的核心架构

在了解Docker的核心架构之前,先简单介绍下容器发展历史吧。

Docker在2013年一炮而红,自那以后持续引起IT界的兴奋,已经成为容器技术的代名词。但此时市场上除了有 Docker 容器,还有很多其他的容器技术,比如:CoreOS的rkt,lxc等。

CoreOS团队除了推出自己的容器软件rkt还精心制作了一个轻量级的基于Linux内核的操作系统。类似于开源项目Docker,rkt是一个允许容器创建的容器运行版本。

如此众多容器技术的出现必然会产生一些问题。例如容器技术的标准到底是什么?容器标准应该由谁来制定?

也许大部分人会说, Docker 已经成为了容器技术的标杆,把 Docker 作为容器技术的标准不就好了?事实并没有想象的那么简单。因为那时候不仅有容器标准之争,编排技术之争也十分激烈。当时的编排技术有三大主力,分别是 Docker Swarm、Kubernetes 和 Mesos 。

Swarm 毋庸置疑,肯定愿意把 Docker 作为唯一的容器运行时,但是 Kubernetes 和 Mesos 就不同意了,因为它们不希望调度的形式过度单一。

在这样的背景下,最终爆发了容器大战,OCI也正是在这样的背景下应运而生。

 

OCI全称为开放容器标准(Open Container Initiative),它是一个轻量级、开放的治理结构。OCI组织在 Linux 基金会的大力支持下,于 2015 年 6 月份正式注册成立。基金会旨在为用户围绕工业化容器的格式和镜像运行时,制定一个开放的容器标准。


目前主要有两个标准文档:容器运行时标准 (runtime spec)和容器镜像标准(image spec)。

正是由于容器的战争,才导致 Docker 不得不在战争中改变一些技术架构。最终形成了下图所示的技术架构。

图片

我们可以看到,Docker 整体架构采用 C/S(客户端(Client) / 服务器(Server))模式,主要由客户端和服务端两大部分组成。


客户端负责发送操作指令,服务端负责接收和处理指令。客户端和服务端通信有多种方式,既可以在同一台机器上通过UNIX套接字通信,也可以通过网络连接远程通信。

以下是关于客户端和服务端的介绍。

 

Docker 客户端

Docker 客户端其实是一种泛称。其中docker 命令是Docker 用户与 Docker 服务端交互的主要方式。
除了使用 docker 命令的方式,还可以使用直接请求REST API 的方式与Docker 服务端交互,甚至还可以使用各种语言的SDK 与Docker 服务端交互。目前社区维护着 Go、Java、Python、PHP 等数十种语言的SDK,足以满足大家的日常需求。

 

Docker 服务端

Docker 服务端是Docker 所有后台服务的统称。其中dockerd 是一个非常重要的后台管理进程,它负责响应和处理来自Docker 客户端的请求,然后将客户端的请求转化为Docker 的具体操作。

例如:镜像、容器、网络和挂载卷等具体对象的操作和管理。

Docker 从诞生到现在,服务端经历了多次架构重构。起初,服务端的组件是全部集成在docker 二进制里。但是从 1.11 版本开始, dockerd 已经成了独立的二进制,此时的容器也不是直接由dockerd 来启动了,而是集成了containerd、runC 等多个组件。

虽然 Docker 的架构在不停重构,但是各个模块的基本功能和定位并没有变化。它和一般的 C/S 架构系统一样,Docker 服务端模块负责和 Docker 客户端交互,并管理Docker 的容器、镜像、网络等资源。

 

Docker 重要组件

Docker 有两个至关重要的组件:runC和containerd。

runC是Docker 官方按照OCI 容器运行时标准的一个实现。通俗地讲,runC 是一个用来运行容器的轻量级工具,是真正用来运行容器的。

containerd是Docker 服务端的一个核心组件,它是从dockerd 中剥离出来的 ,它的诞生完全遵循OCI 标准,是容器标准化后的产物。containerd通过containerd-shim 启动并管理runC,可以说containerd真正管理了容器的生命周期。
图片

通过图3可以看到,dockerd通过 gRPC 与containerd 通信,由于dockerd与真正的容器运行时,runC 中间有了containerd 这一 OCI 标准层,使得dockerd 可以确保接口向下兼容。

gRPC 是一种远程服务调用。想了解更多信息可以参考https://grpc.io
containerd-shim 的意思是垫片,类似于拧螺丝时夹在螺丝和螺母之间的垫片。
containerd-shim 的主要作用是将 containerd 和真正的容器进程解耦,使用 containerd-shim 作为容器进程的父进程,从而实现重启dockerd 不影响已经启动的容器进程。

了解了 dockerd、containerd 和 runC 之间的关系,下面可以通过启动一个 Docker 容器,来验证它们进程之间的关系。

 

Docker 各组件之间的关系

以Docker 的 18.09.2 版本为例(如果以下命令在执行时,没有输出预期结果,考虑可能是Docker 版本的问题):
首先通过以下命令来启动一个docker101tutorial 容器:

$ docker run -d docker101tutorial sleep 5000

 

容器启动后,通过以下命令查看一下 dockerd 的 PID:

$ sudo ps aux |grep dockerd
 
root      4247  0.3  0.2 1447892 83236 ?       Ssl  Jul09 245:59 /usr/bin/dockerd

 

通过上面的输出结果可以得知 dockerd 的 PID 为 4247。为了验证上图中Docker 各组件之间的调用关系,下面使用 pstree 命令查看一下进程父子关系:

$ sudo pstree -l -a -A 4247
 
dockerd
 
  |-containerd --config /var/run/docker/containerd/containerd.toml --log-level info
 
  |   |-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/d14d20507073e5743e607efd616571c834f1a914f903db6279b8de4b5ba3a45a -address /var/run/docker/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
 
  |   |   |-sleep 5000

 

实际上在dockerd 启动的时候,containerd 就随之启动了,dockerd 与containerd 一直存在。

当执行 docker run 命令(通过docker101tutorial 镜像创建并启动容器)时,containerd 会创建 containerd-shim 充当 “垫片”进程,然后启动容器的真正进程sleep 5000。由此看来这个过程和架构图是完全一致的。

以上内容就是今天分享的全部了,需要掌握Docker 架构核心设计理念:镜像、容器、仓库的原理知识,才能更好的去运用和使用Docker。

 

欢迎关注【无量测试之道】公众号,回复【领取资源】,
Python编程学习资源干货、
Python+Appium框架APP的UI自动化、
Python+Selenium框架Web的UI自动化、
Python+Unittest框架API自动化、

资源和代码 免费送啦~
文章下方有公众号二维码,可直接微信扫一扫关注即可。

备注:我的个人公众号已正式开通,致力于测试技术的分享,包含:大数据测试、功能测试,测试开发,API接口自动化、测试运维、UI自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:

 添加关注,让我们一起共同成长!

posted on 2021-01-30 16:41  Wu_Candy  阅读(832)  评论(0编辑  收藏  举报