Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 的分层设计

news2024/10/7 17:34:27

容器技术是云原生的核心技术之一,利用容器化技术,可以将微服务以及它所需要的配置、依赖关系、环境变了等都可以便捷地部署到新的服务器节点上,而不用再次重新配置,这就使得微服务具备了强大的可移植性。

二、Docker 的分层设计

分层设计是 Docker 的一个非常核心的实现思路,只有了解分层设计的原理,才能更好地理解 Docker 镜像、容器等运行过程。

1、分层设计与写时拷贝

应用的部署通常需要依赖许多外部环境,如操作系统、应用服务器、虚拟机、库文件、应用程序包和配置文件等。为了实现一次构建,到处运行的目标,必须将这些依赖项打包到一起,以屏蔽环境的差异性。然而,操作系统本身就有数 G 字节的大小,如果将所有依赖项都打包进来,将导致部署包过大,难以快速分发和部署。

为解决部署包过大使分发下载慢的问题,Docker引入了分层设计的概念。将应用分解为多个层次,如操作系统层、库和第三方软件层、应用软件包和配置文件层。如果两个应用共享相同的底层,它们可以共享这些层次。例如,如果应用 A 和应用 B 使用相同的操作系统版本,则它们可以共享操作系统层。当安装应用 A 时,只需下载操作系统层;而安装应用 B 时,则无需再次下载操作系统层,只需下载其依赖包和应用软件包。这种设计大大减少了安装部署时的下载量。

(图片来自于网络)

然而,共享层次也会带来共性和个性的冲突。例如,应用 A 可能需要修改操作系统的某些配置,而应用 B 则不需要。为解决这一冲突,Docker 参考了 Java 的子类继承机制,设计了有优先级的层次。当上层和下层存在相同的文件或配置时,上层将覆盖下层,并以上层的数据为准。每个应用被赋予一个优先级最高的空白层,如果需要修改下层文件,则将该文件复制到优先级最高的空白层进行修改,这种策略称为写时拷贝(Copy-on-Write,COW)。这样,对应用 A 而言,文件已经被成功修改;而对应用 B 而言,文件保持不变。

(图片来自于网络)

Docker 的分层设计和写时拷贝策略有效解决了包含操作系统的应用程序过大的问题,但并未解决虚拟机启动慢的瓶颈。主流虚拟机(如KVM、Xen、VMWare、VirtualBox等)通常较为笨重,因为它们需要通过软件模拟硬件指令来启动,导致启动一个虚拟机通常需要数分钟时间。这显然无法满足云环境下对于快速弹性伸缩的需求。那么,如何实现虚拟机的轻量化呢?

容器类虚拟机,以 LXC 和 OpenVZ 为代表,采用了一种内核虚拟化技术。这些容器与宿主机共享相同的 Linux 内核,无需进行指令级模拟,因此性能消耗非常小,几乎与普通进程相当。Docker 就是利用 LXC(后来发展出Libcontainer)实现了虚拟机的轻量化。

Libcontainer 是 Docker 中用于容器管理的核心组件。它使用 Go 语言编写,通过管理 namespaces、cgroups、capabilities 以及文件系统来控制容器。最初,Docker 采用了基于 LXC 的开源容器管理引擎,但随着发展,Docker 开始设定更广泛的目标,即反向定义容器的实现标准,并将底层实现抽象化为 Libcontainer 的接口。这意味着,底层容器的实现方式变得灵活多样,只要满足 Libcontainer 定义的一组接口,Docker 就能够运行。这也为 Docker 实现全面跨平台带来了可能。

在 Docker 的官方仓库中,只需包含完整的文件系统和程序包,无需动态生成新文件。当将镜像下载到宿主机以提供服务时,可能需要修改文件(如应用启动参数、日志输出),此时就需要空白层进行写时拷贝。因此,Docker 将镜像和容器这两种不同状态进行了区分,如图所示:

(图片来自于网络)

仓库中的应用以镜像的形式存储。将镜像从 Docker 镜像仓库下载到本地宿主机,然后以此镜像为模板启动应用,这便形成了容器。镜像为只读状态,而容器则可读写。它们之间的关系如下图:

(图片来自于网络)

2、镜像分层管理

通过 Docker 的分层设计,我们已经了解了镜像的分层原理。现在,我们将通过具体的例子来看一个镜像层次结构,加深对 Docker 镜像的理解。

Docker 镜像分为基础镜像和扩展镜像。基础镜像提供操作系统内核,通常是各种Linux发行版的镜像,比如 Ubuntu、Debian、CentOS 等。基础镜像有两个含义:

  • 从空白镜像构建,不依赖其他镜像
  • 其他镜像以基础镜像为基准进行扩展

Linux 系统包含内核空间 kernel 和用户空间 rootfs 两部分。容器使用各自的用户空间 rootfs,但共享宿主机的内核空间 kernel,形成基础镜像的最底层结构。

基础镜像

不同 Linux 发行版的区别主要在用户空间 rootfs,比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包,而 CentOS 7 使用 systemd 和 yum。这些区别并不大,因为 Linux 内核几乎相同。因此,Docker 能够同时支持多种 Linux 镜像,模拟出多种操作系统环境。

不同 Linux 发行版本的主要区别是 rootfs,kernel 都一样

一台宿主机上的所有容器都共用宿主机的 kernel,在容器中无法对 kernel 升级。大部分镜像是基于基础镜像构建的,所以通常使用的是官方发布的基础镜像,可以在 Docker Hub 里找到。

ADD centos-8-container.tar.xz / 命令将本地的 CentOS 8 的 tar 包添加到镜像,并解压到根目录下,生成 /dev、/proc、/bin、/usr、/var等。我们既可以自己构建基础镜像,也可以直接使用Docker Hub 上已有的基础镜像。最新的 CentOS 镜像只有 220 MB,比较小。这是因为 Docker 镜像在运行时直接使用 Docker 宿主机的 kernel,因此 CentOS 镜像中只包含用户空间 rootfs 部分的程序包。

新镜像类似于 CentOS 镜像,是通过在基础镜像上逐层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。如果多个镜像都是从相同的基础镜像构建而来,那么 Docker 宿主机只需在磁盘上保存一份基础镜像,并且在内存中也只需加载一份基础镜像,就可以为所有容器提供服务。此外,镜像的每一层都可以被共享。在创建镜像时,分层设计让 Docker 只保存我们添加和修改的部分内容,其他内容基于基础镜像,无需额外存储,只需读取基础镜像即可。因此,当我们创建多个镜像时,它们都共享基础镜像,节省了磁盘空间。

如果多个容器共享一份基础镜像,那么当某个容器修改了基础镜像的内容(例如 /etc 下的文件),其他容器的 /etc 是否也会被修改呢?当一个容器启动时,会在镜像的顶部加载一个新的可写层,通常称为“容器层”,而位于其下方的部分称为“镜像层”。容器层是可读写的,所有文件变更都发生在这一层,而镜像层则只允许读取。

(容器和镜像分层结构)

镜像的分层结构即镜像制作过程中的操作,通过 docker history <镜像id / 镜像名称> 命令即可查看。

通过 docker image inspect <镜像id / 镜像名称>命令查看镜像的元数据信息,其中包括镜像的分层信息。

3、镜像版本变更管理

在软件开发中,版本迭代和回退是常见的需求。Docker 在版本变更管理方面也有着独特之处。考虑一个应用的 Docker 镜像,比如1.0版本,它包含三层:第一层 1 GB,第二层 300 MB,第三层 10 MB。现在需要做以下修改:

  • 在第一层修改文件 A
  • 删除第二层的文件 B
  • 添加一个新文件 C

对于这些修改需求,Docker 会新增一个第四层,使版本变更为 1.1。具体处理方法如下:

  • 将文件A复制到第四层,并修改内容为 A'
  • 在第四层中将文件B标记为不存在
  • 在第四层创建新文件C

通过增加第四层,完成版本变更为 1.1。上传 1.1 版本到 Docker 镜像仓库时,由于前三层已存在于仓库中,只需上传第四层(大小仅为 3 MB),大大减小了上传程序包的大小。同样,应用方只需下载第四层即可从 1.0 版本快速升级到 1.1 版本,因为它已经拥有了前三层的镜像,使得版本升级变得非常迅速轻量。

总之,Docker不仅能够控制版本变更,还能利用分层特性实现增量更新。这种分层设计对于大规模分布式环境下的版本分发部署至关重要,为云原生环境下的持续集成/持续部署提供了可靠的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1509296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

研发效能DevOps: OpenEuler 部署 drone 持续集成平台

目录 一、实验 1.环境 2.OpenEuler 部署 drone 持续集成平台 二、问题 1.drone登录失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注LinuxopenEuler22.03 LTS SP2 192.168.204.145&#xff08;动态&#xff09; 192.168.204.141&…

github 中的java前后端项目整合到本地运行

前言: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未…

安卓多个listView拖动数据交换位置和拖动

注意这里只是给出大概思路&#xff0c;具体可以参考修改自己想要的 public class MainActivity extends AppCompatActivity {private ListView listView1;private ListView listView2;private ArrayAdapter<String> adapter1;private ArrayAdapter<String> adapter…

搭建交换机模拟环境及SSH连接,华为NSP软件入门使用教程

搭建交换机模拟环境及SSH连接&#xff0c;华为NSP软件入门使用教程 如果你是通过搜索搜到了这篇文章&#xff0c;那么一定是工作或者学习中需要用交换机&#xff0c;但是又没物理机测试学习&#xff0c;所以需要搭建本地的虚拟环境学习。 这篇文章是我进行交换机命令入门学习写…

阅读欣赏推荐之(三)——纪录片《地平线系列:大数据时代》

现今的我们正处于一个时代转型中&#xff0c;因为科技的发展与互联网的日益强大&#xff0c;数据将逐步取代旧事物&#xff0c;创造出新事物。当今社会以一种前所未有的方式&#xff0c;通过对海量数据进行分析&#xff0c;获得巨大价值的产品和服务&#xff0c;或深刻的洞见。…

Jmeter+Ant+Git/SVN+Jenkins实现持续集成接口测试,一文精通(二)

前言 上篇内容已经介绍接口测试流程以及了解如何用jmeter接口测试&#xff0c;本篇将介绍如何在实战中应用 一、Jmeter接口关联 1.使用正则表达式实现接口关联&#xff08;可以作用于任意值&#xff09; 如果说一个请求里面有多次请求服务器。 2.使用Jsonpath表达式实现接口关…

【CV论文阅读】【计算机视觉中的Transformer应用综述】(1)

0.论文摘要 摘要——自然语言任务的Transformer model模型的惊人结果引起了视觉社区的兴趣&#xff0c;以研究它们在计算机视觉问题中的应用。在它们的显著优点中&#xff0c;与递归网络例如长短期记忆&#xff08;LSTM&#xff09;相比&#xff0c;Transformer能够模拟输入序…

Cocos2dx-lua ScrollView[二]进阶篇

一.概述 本文缩写说明:sv = ScrollView, item代表ScrollView的一个子节点 如果对sv熟系程度还不够,请阅读基础篇: Cocos2dx-lua ScrollView[一]基础篇-CSDN博客 本文介绍sv的一种封装类库,来实现快速创建sv,有如下几个优点: 1.item的位置通过参数控制,提高开发效率…

【MySQL】1.在Centos 7上如何卸载/安装/配置MySQL(保姆级教程)

MySQL 在 Centos 7环境安装 说明&#xff1a; • 安装与卸载中&#xff0c;用户全部切换成为root&#xff0c;⼀旦安装&#xff0c;普通用户能使用的 • 初期练习&#xff0c;mysql不进行用户管理&#xff0c;全部使用root进行&#xff0c;尽快适应mysql语句&#xff0c;后⾯学…

机器学习,剪刀,石头,布

计算机视觉:剪刀,石头,步 TensorFlow AI人工智能及Machine Learning训练图集的下载建立分类模型并用图像进行训练检验模型总结当前AI Machine Learning 异常火爆,希望在MCU上使用机器学习,做图像识别的工作。看到一个剪刀,石头,步的学习程序,给大家分享一下。 TensorFl…

记录一个vue编辑的移动端页面

<template><div class"wrap"><el-form :model"queryParams" ref"queryForm" size"small" :inline"true" label-width"120px"><el-form-item label"班级" prop"classId"…

K8s — PVC|PV Terminating State

在本文中&#xff0c;我们将讨论PV和PVC一直Terminating的状态。 何时会Terminting? 在以下情况下&#xff0c;资源将处于Terminating状态。 在删除Bounded 状态的PVC之前&#xff0c;删除了对应的PV&#xff0c;PV在删除后是Terminting状态。删除PVC时&#xff0c;仍有引用…

使用飞书机器人发送消息与文件

本文默认你已拥有一个机器人&#xff0c;如果没有请点击以下链接创建机器人 检查机器人权限 如果需要跨部门发送消息&#xff0c;检查是否开通跨部门权限 在发布版本时选择作用范围为所有员工 机器人发送消息需要获取以下权限&#xff1a; 通过手机号或邮箱获取用户 ID查看…

ETL的数据挖掘方式

ETL的基本概念 数据抽取&#xff08;Extraction&#xff09;&#xff1a;从不同源头系统中获取所需数据的步骤。比如从mysql中拿取数据就是一种简单的抽取动作&#xff0c;从API接口拿取数据也是。 数据转换&#xff08;Transformation&#xff09;&#xff1a;清洗、整合和转…

Flutter可重排的列表控件ReorderableListView详解

文章目录 ReorderableListView 介绍主要属性使用示例注意事项 ReorderableListView 介绍 ReorderableListView 是 Flutter 中一个可重排的列表控件&#xff0c;允许用户通过拖动来改变列表项的顺序。它继承自 ListView&#xff0c;并提供了一些额外的功能来实现重排功能。 主…

应用方案 | DCDC电源管理芯片MC34063A

DCDC电源管理芯片 MC34063A MC34063A 为一单片 DC-DC 变换集成电路&#xff0c;内含温度补偿的参考电压源&#xff08;1.25V&#xff09;、比较器、能有效限制电流及控制工作周期的振荡器&#xff0c;驱动器及大电流输出开关管等。外配少量元件&#xff0c;就能组成升压、…

Mysql 学习(十五)redo 日志

redo 日志 什么是redo日志&#xff1f;在说这个之前我们先来想一个场景&#xff0c;在访问磁盘的页面之前&#xff0c;我们会先把页面缓存到Buffer Pool之后&#xff0c;才会访问。写页面的时候也会先将buffer pool中的页面修改之后&#xff0c;然后在某个时机才会刷新到磁盘中…

Centos7 安装mongodb 7.0

官方手册参考&#xff1a; https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-red-hat/ Mongodb支持的版本 安装 MongoDB 社区版 按照以下步骤使用包管理器安装 MongoDB Community Edition yum。 配置包管理系统 ( yum) 创建一个/etc/yum.repos.d/mongodb-o…

uni-app微信小程序上拉加载,下拉刷新

pages.json配置官网链接 onPullDownRefresh、onReachBottom函数跟生命周期同级 data() {return {orderList:[],total: null, //总共多少条数据page: 1,pageSize: 10,} }, onLoad() {}, mounted(){this.getInfo() }, methods:{getInfo(){API.getListxxx().then(res > {const…

sensitive-word 敏感词 违规文字检测

1、快速开始 - JDK1.7- Maven 3.x 2、Maven 引入 <!-- https://mvnrepository.com/artifact/com.github.houbb/sensitive-word --><dependency><groupId>com.github.houbb</groupId><artifactId>sensitive-word</artifactId><version…