2023-08-23:Docker概念

学习自:02 核心概念:镜像、容器、仓库,彻底掌握 Docker 架构核心设计理念

1、Docker核心概念

Docker的操作围绕镜像、仓库、容器三大核心概念展开。

镜像

镜像是只读文件、目录的组合,它包含了容器运行时所需的所有基础文件和配置信息,是容器启动的基础

如果你想启动一个容器,那首先必须有一个镜像。镜像Docker容器启动的先决条件

如果要使用一个镜像,通常有两种方式:

  • 自己创建镜像。通常情况下,一个镜像是基于一个基础镜像构建的,我们可以在基础镜像添加一些用户自定义的内容。例如,我们可以基于centos镜像制作业务镜像,首先安装nginx服务,然后部署我们的应用程序,最后做一些自定义配置,这样一个业务镜像就完成了;
  • 镜像仓库拉取别人制作好的镜像。一些常用软件或者系统(nginx、Ubuntu、centos、mysql等)都有官方已经制作好的镜像,我们可以去Docker Hub 下搜索并下载它们。

容器

容器是镜像运行的实体

镜像静态的只读文件,容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。也就是说,容器中运行着真正的应用进程,容器有初建、运行、停止、暂停、删除五种状态。

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

仓库

Docker镜像仓库,类似于代码仓库,用于存储和分发Docker镜像

镜像仓库分为公共私有镜像仓库Docker Hub是Docker官方的公开镜像仓库,它不仅有很多应用或者操作系统的官方镜像,还有很多组织或者个人开发的镜像供我们免费下载使用。除了公开镜像仓库,我们也可以构建自己的私有镜像仓库。

 

仓库-镜像-容器关系图

从这张图中可以看出,容器是由镜像创建的,一个镜像可以创建多个容器,容器是镜像运行的实体,仓库是用于存放和分发镜像。

2、容器的发展史

容器技术随着Docker的出现变得炙手可热,很多公司都在积极拥抱容器技术。但是容器的标准是什么,由谁制定却是在Docker出现后需要讨论的问题。

除了容器标准之外,容器编排之争也很激烈,Docker出现后有三家容器编排技术:Docker Swarm、Kubernetes、Mesos。它们希望有不同的调度形式

在这种背景下,OCI应运而生。

OCI,即Open Container Initiative 开放容器标准,是一个轻量级、开放治理结构。OCI旨在为用户围绕工业化容器格式运行时制定一个开放的容器标准。目前主要有两个标准文档:容器运行时标准(runtime spec)、镜像标准(image spec)

现在的Docker技术架构如下图所示

Docker整体架构采用C/S(客户端/服务器)模式C端负责发送操作命令S端负责接收和处理指令

C和S间存在多种通信方式,既可以在同一台及其上通过UNIX套接字通信,也可以通过网络连接远程通信

Docker客户端

Docker客户端其实是个泛称。其中docker命令Docker用户Docker服务端交互的主要方式。

除了用docker命令外,还可以使用直接请求REST API的方式与Docker服务端进行交互,甚至还能用各种语言的SDK来与Docker进行交互。目前社区维护着Go、Java、Python、PHP等数十种语言的SDK,足以满足我们的日常需求。

Docker服务端

S端是Docker所有后台服务的统称。其中dockerd是一个重要的后台管理程序,它负责响应和处理来自C端的请求,再将C端请求转化为Docker的具体操作。例如镜像、容器、网络、挂载卷等具体对象的操作与管理。

从1.11版本开始,dockerd已经成为了独立二进制,此时容器也不是直接由dockerd来启动了,而是集成了containerd、runC等多个组件

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

3、Docker重要组件

在Docker的安装路径下,输入指令ls就能看到与docker有关的二进制文件。

如果采用dnf安装时未指定目录,那默认安装目录在/usr/bin下,可以输入以下指令来查找(这些项不一定是在最后或者最前边,但是大多数情况下是挨在一起的):

复制代码
ls -trl /usr/bin
-rwxr-xr-x.   1 root root        5190 7月  22 04:33 dockerd-rootless.sh                         
-rwxr-xr-x.   1 root root       13951 7月  22 04:33 dockerd-rootless-setuptool.sh               
-rwxr-xr-x.   1 root root    99975880 7月  22 04:38 dockerd                                     
-rwxr-xr-x.   1 root root     2180492 7月  22 04:38 docker-proxy                                
-rwxr-xr-x.   1 root root    35913304 7月  22 04:39 docker                                      
-rwxr-xr-x.   1 root root    12250248 7月  22 04:40 rootlesskit                                 
-rwxr-xr-x.   1 root root     7852016 7月  22 04:40 rootlesskit-docker-proxy                    
-rwxr-xr-x.   1 root root    27178688 7月  30 03:50 ctr                                         
-rwxr-xr-x.   1 root root     9502720 7月  30 03:50 containerd-shim-runc-v2                     
-rwxr-xr-x.   1 root root     9474048 7月  30 03:50 containerd-shim-runc-v1                     
-rwxr-xr-x.   1 root root     7352320 7月  30 03:50 containerd-shim                             
-rwxr-xr-x.   1 root root    52345280 7月  30 03:50 containerd                                  
-rwxr-xr-x.   1 root root    13623192 7月  30 03:50 runc  
复制代码

可以看到Docker有很多组件与工具,这里先介绍runC与containerd

  • runC:Docker官方按照OCI容器运行时标准的一个实现。换句话说,runC是一个用来运行容器的轻量级工具,是真正用来运行容器的。
  • containerd:Docker的S端一个核心组件,它是从dockerd中剥离出来的,是OCI容器标准化的产物。containerd通过containerd-shim启动并管理runC,可以说containerd真正管理了容器的生命周期

S端组件调用关系图

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

  • gRPC是一种远程服务调用。官网:https://grpc.io
  • containerd-shim作用是将containerd真正容器进程解耦,使用container-shim作为容器进程的父进程,从而实现重启containerd不影响已启动的容器进程

为了了解docker、containerd、runC之间的关系,可以通过启动一个Docker容器来验证:

启动一个busybox容器

1
docker run -d busybox sleep 3600

查看dockerd的PID

1
2
ps -ef | grep dockerd
root      4147     1  0 09:28 ?        00:00:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

通过该结果可以得到dockerd的PID为1225,为了验证之前那张图(最近那张)中Docker各组件间的调用关系,可以用pstree来查看一下进程父子关系:

1
2
3
4
5
pstree -l -a -A 4147
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 3600

以上为教程中所讲的显示内容,我自己实操时并没有显示出这一结果。

事实上,dockerd启动时,containerd就随之启动了,dockerd与containerd一直存在,当执行docker run命令(即通过busybox镜像创建并启动容器)时,containerd会创建containerd-shim,然后启动容器的真正进程sleep 3600。这个过程和架构图是完全一致的。

 

 

回顾

1、Docker有三大概念:镜像、容器、仓库

镜像

镜像是静态、未运行的文件与目录的组合,这些文件、目录包含了容器运行时所需的基础文件和配置信息,是容器运行的依据。另外,这些文件、目录都是只读

容器的启动依赖于一个镜像,没有镜像就启动不了容器。

镜像的获取和使用方式有两种:

  • 自己创建。自建的镜像一般依赖于某个基础镜像,通过在基础镜像上添加一些用户自定义的内容,来实现特定的需求。
  • 仓库拉取别人制作好的镜像。常用软件或系统都有官方制作好的镜像,我们可以去Docker Hub搜索并下载它们。

一个业务镜像的制作过程:挑选某个基础镜像(如centos镜像)作为原材料,在其基础上修改内容,例如安装nginx服务,部署我们的应用程序,再加一些自定义配置。这样就得到了一个业务镜像。

容器

之前说过镜像是静态文件的组合,那容器就是运行起来的镜像实体

镜像是只读文件,容器则带有运行时的可写文件层,容器中的进程属于运行状态,其中运行着真正的应用程序。

容器本身是主机上运行的一个进程,但是容器内的进程看不到主机上的资源(进程、环境变量、网络)的情况,因为实现容器需要命名空间隔离系统资源的限制

能否看到主机上的资源容器与主机进程的本质区别。

仓库

仓库理解起来最简单,就是存放镜像的空间。

仓库分为公有私有两种:

  • 公有是指官方提供的,比如Docker Hub,它里边有很多应用和OS的官方镜像。
  • 私有是指我们在实际的业务工作中构建出的自己的私有镜像仓库。

2、OCI:Open Container Initiative 开放容器标准,制定了两个标准:容器运行时标准、镜像标准。

3、Docker技术架构

Docker是一个C/S模式的架构:C发送操作命令,S接收和处理命令。

C和S如果位于同一台,可以通过Socket通信,位于远程连接可以用网络连接远程通信。

4、Docker C端

C与S的交互方式有两种:docker命令(主要)、直接请求REST API、各种语言的SDK。

5、Docker S端

1)S端是所有Docker后台服务的统称;

2)dockerd是一个重要的后台管理程序,负责响应、处理来自C端的请求,再将C端请求转为具体的Docker操作(对镜像、容器、网络、挂载这些具体对象的操作);

3)Docker经历了多次重构,1.11版本之后,dockerd成为了独立的二进制文件,Docker也不是直接由dockerd启动了,而是集成了containerd、runC等多个组件;

4)虽然经历了多次重构,但是C/S的结构并没有变化,各个模块的功能与定位也没变。

6、在docker安装路径下,可以看到一些二进制文件:

containerd
containerd-shim
ctr
docker
docker-init
docker-proxy
dockerd
runc

其中:

  • runC是Docker官方按照OCI运行时标准化的实现。用于运行容器的轻量级工具
  • containerd是Docker S端的核心组件,是从dockerd中剥离出来的OCI容器标准化的产物。container通过containerd-shim启动并管理runC,它是容器生命周期的真正管理者

7、S端

1)dockerd与containerd进行通信(通过gRPC,一种远程服务调用),containerd是一个OCI标准层,可以保证接口向下兼容。

2)containerd-shime将containerd与真正容器进程解耦,使用shim作为容器进程的父进程,可以保证重启containerd不影响已启动的容器进程。

3)runc负责管理容器运行

8、

1
docker run -d busybox sleep 3600

dockerd启动时(systemctl start docker),containerd就随之启动了,二者会一直存在。当docker run创建镜像并启动容器时,containerd会创建containerd-shim,再启动容器的真正进程 sleep 3600。此为之前C/S架构图中所说的工作流程。

posted @   ShineLe  阅读(54)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示