[4435] 21 容器方案:从构建到部署,容器化方案的优势有哪些?

news/2024/12/28 18:05:06/文章来源:https://www.cnblogs.com/KooTeam/p/18637766

上节课我们主要介绍了部署系统中各耗时环节的一些常用优化方案。课后思考题是:课程中提到了几种利用缓存的优化方案呢?如果你认真学习了课程内容,不难发现我一共提到了三种基于缓存的优化方案,它们分别是:多项目共用依赖缓存、依赖安装目录的缓存以及构建过程的持久化缓存备份。这些缓存方案不仅可以运用到传统的部署方式中,在今天介绍的容器化部署方案中也有各自的用武之地。

下面我就来介绍本节课的第一个话题:什么是容器化呢?

容器化的基本概念

什么是容器化

容器化(Containerization)通常是指以 Docker 技术为代表,将操作系统内核虚拟化的技术。和传统的虚拟机相比,容器化具有占用空间更小、性能开销更低、启动更快、支持弹性伸缩以及支持容器间互联等优势。

下面介绍 Docker 的几个基本概念。

Docker

通常我们提到的 Docker 是指运行在 Linux/Windows/macOS 中开源的虚拟化引擎,用于创建、管理和编排容器(此外,Docker 也是发布和维护该开源项目的公司名称)。

镜像

Docker 中的镜像(Image)是指用于创建容器实例的基础虚拟化模板。对于开发人员来说,可以把镜像理解为编程语言中的类:通过一个镜像可以创建多个容器实例,镜像之间也存在继承关系。通过 Docker 引擎可以构建、删除镜像,还可以将本地镜像 push 到远程仓库或者从远程拉取。例如一个基于 node:14 的镜像,在创建时不光包含了运行 node14 版本所需的 Linux 系统环境,还包含了额外打入到镜像内的 Yarn 程序。

容器

容器(Container)是 Docker 中的核心功能单元。通常一个容器内包含了一个或多个应用程序以及运行它们所需要的完整相关环境依赖。例如,基于上面例子中的 node:14 镜像,就可以创建出对应版本 NodeJS 的独立运行环境。通过 Docker 引擎可以对容器进行创建、删除、停止、恢复、与容器交互等操作。

数据挂载与数据卷

通常情况下容器内的基础数据来自创建容器的镜像。创建容器后,在容器内执行的命令如果导致容器内的数据产生变化,这些变更的数据会在容器删除的同时被清除,无法持久化保留。如果要解决持久化保留数据,可以采取两种方式:挂载容器的宿主环境(即执行启动容器命令所在的服务器)的目录或使用数据卷。数据卷可以理解为通过 Docker 引擎创建的宿主环境下的独立磁盘空间,用于在容器内读写数据,生命周期独立,不受容器生命周期的影响。

网络

Docker 容器的网络有多种驱动类型,例如 bridge、host、overlay 等。其中默认的 bridge 类型类似网桥,用于点对点访问容器间端口或者将容器端口映射到宿主环境下。而 host 则是直接使用宿主环境的网络。更多网络模型介绍可参照官方说明文档。

容器化的构建部署

在了解了容器化的基本概念后,我们再来看看什么是容器化的构建部署。

顾名思义,容器化的构建部署是把原先在部署服务器中执行的项目部署流程的各个环节,改为使用容器化的技术来完成,具体可以划分为操作镜像和操作容器两个阶段。

镜像阶段

镜像阶段的主要目标是创建一个用于部署代码的容器环境的工作镜像。以前端项目为例,工作镜像中一般会包含:特定版本的 node 环境、git、项目构建所需的其他依赖库等。有了这样的环境就可以在对应的容器中执行各部署环节。

构建镜像的具体内容写在 Dockerfile 文件中,例如下面的代码:

# 通过FROM指定父镜像
FROM node:12-slim
# 通过RUN命令依次在镜像中安装git,make和curl程序
RUN apt-get update
RUN apt-get -y install git
RUN apt-get install -y build-essential
RUN apt-get install -y curl

这是一个基本的包含 node、git 等依赖程序的部署工作环境的镜像内容。

然后在 Dockerfile 所在目录下执行构建命令,即可创建相应镜像,如下所示:

docker build --network host --tag foo:bar .

容器阶段

容器阶段的主要目标就是基于项目的工作镜像创建执行部署过程的容器,并操作容器执行相应的各部署环节:获取代码、安装依赖、执行构建、产物打包、推送产物等。操作分为两个部分,创建容器与执行命令,如下面的代码所示:

# 创建容器
docker run -dit --name container_1 foo:bar bash
# 容器内执行命令
docker exec -it container_1 xxxx

容器化部署过程的优势

与传统的在单台服务器上以目录区分不同部署项目的方式相比,容器化的构建部署过程有以下优点:

环境隔离

每个项目在独立的容器内执行构建部署过程,保证容器与宿主环境之间,容器与容器之间的环境隔离,防止原先共用一台服务器时可能产生的互相影响(例如项目脚本中修改了全局配置或环境变量等)。同时,环境隔离还可以保证每个项目都可以自由定制专属的环境依赖,而不必担心对其他项目产生影响。

多环境构建

使用容器化部署,可以方便地针对同一个项目生成多套不同的构建环境,达到类似 Github Actions 中的矩阵构建效果,使项目可以同时检测多套环境下的集成过程。

便于调试

用户可通过 Xterm+SSH 的方式,通过浏览器访问部署系统中的容器环境。同传统的部署方式相比,用容器化的方式可以在部署遇到问题时让用户第一时间进入容器环境中进行现场调试,效率和便捷性大大提升。之前介绍过的部署工具 CircleCI 中就提供了这一调试功能。

环境一致性与迁移效率

由于部署过程的工作环境以 Docker 镜像的方式独立制作和存储,因此可以在支持 Docker 引擎的任意服务器中使用。使用时提供一致的工作环境,无须考虑不同服务器操作系统的差异。在迁移时也可以做到一键迁移,无须重复安装环境依赖。

容器化部署过程的挑战及建议

尽管容器化的部署方式有上述优势,但也面临一些问题,例如缓存方面和性能方面的问题等。

缓存问题

项目在独立容器中构建部署时,首先面临的就是缓存方面的问题:

  • 依赖缓存:默认情况下,容器内的依赖缓存目录与宿主环境缓存目录不互通,这就导致每次依赖安装时,都无法享受宿主环境缓存带来的效率提升。同时,每次部署流程都在新容器中进行,这也导致在依赖安装的过程中,也无法读取历史依赖安装后的缓存数据。要解决这类问题,可以从两方面入手:生成容器时挂载宿主环境依赖缓存目录,以及上节课中提到的安装目录缓存。

  • 构建缓存:在传统的服务器中执行部署时,可以通过留存历史构建目录的方式来保留构建缓存数据。而在容器化的情况下,每次部署过程都会基于新容器环境重新执行各部署环节,构建过程的缓存数据也会随着部署结束、容器移除而消失。因此在这种部署方式中,尤其需要重视持久化缓存数据的留存问题。你同样可以考虑从两个方向解决:在宿主环境中创建构建缓存目录并挂载到容器中,并在项目构建配置中将缓存目录设置为该目录,这样就可以将缓存直接写入宿主服务器目录中。或者按照上节课提到的持久化缓存的备份与还原方案,将缓存备份到宿主服务器或远程存储服务器中,之后在新部署流程中进行还原使用。

性能问题

通常情况下,与传统的服务器部署相比,容器化部署并没有明显的性能差异,但是在实践中也存在一些性能方面的特殊情况:

  • 容器资源限制:在创建容器时可以通过参数来限制容器使用的 CPU 核心数和内存大小。和在普通服务器中执行部署时,完整使用所有系统资源的方式相比,限制系统资源的方式会在一定程度上导致执行过程性能的降低。在多项目使用的容器化集群方案中,这种限制通常是必要的,只是对于性能降低明显的项目而言,可以考虑在设置中分配更多的资源以提升执行效率。

  • copy-to-write:性能问题的另一方面则体现在它独特的数据存储方式上。和传统的磁盘读写方式不同,容器中的数据是分层的,环境的数据来自镜像层,而新增的数据则来自写入容器层。在读取数据时,数据来自镜像层还是容器层并没有差别,但当修改数据时,如果修改或删除的是镜像层的数据,容器会先将数据从镜像层复制到容器层,然后进行相应操作。这种先复制后写入的模式称为 copy-to-write。因此,如果在容器的部署流程中涉及对镜像层数据的修改时,执行起来会比在普通服务器中的操作耗费更多时间。举个极端的例子,如果我们把项目的依赖安装过程写入构建镜像中,然后在容器内移动 node_modules 目录,会发现这个操作耗费的时间几乎等同于复制完整目录的时间。而同样的移动操作在普通服务器中几乎是瞬间完成的。因此,在使用容器化部署时,需要尽量避免将可变数据写入镜像中。

总结

这节课我们首先了解了以 Docker 为代表的容器化技术的基本概念:镜像、容器、数据挂载和网络等。然后讨论了容器化的构建部署需要经历的流程,先创建镜像,然后根据镜像创建容器,最后在容器内执行相关部署环节。接着分析了容器化部署的优势和劣势:容器化部署具有隔离性高、支持多环境矩阵执行、易于调试和环境标准化等优势,同时在使用时也需要额外注意对应的缓存和性能问题。

本节课的思考题是:容器化技术不仅可以应用在部署过程中,还更广泛地被应用在部署后的项目服务运行中。试比较这两种场景下对容器化技术需求的差异性。

下节课我们将进入部署效率模块的最后一节课:如何搭建基本的前端高效部署系统。


精选评论

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 7~8次题目集总结

本次完成了7~8次的题目集是接着上次的家居强电电路模拟程序-1和家居强电电路模拟程序-2后续迭代功能拓展 完成了家居强电电路模拟程序-3和家居强电电路模拟程序-4 家居强电电路模拟程序-3相比较之前的升级了电路其中线路中包含多个串联起来的并联电路以及增加了新的受控电路元件…

[4422] 08 无代码工具:如何做到不写代码就能高效交付?

在开始今天的课程前,我们先来简单回顾下上节课的思考题:低代码工具主要面向什么样的用户群体呢?低代码工具本质上是对组件化开发流程的简化,但在开发过程中,仍然可能进行编码调试。因此,它面向的用户群体应该是具有一定技术基础的开发人员,专业的后端开发也可以使用这类…

[4421] 07 低代码工具:如何用更少的代码实现更灵活的需求?

在进入到这一课的内容之前先让我们来回顾下,通过脚手架工具生成初始化代码,以及通过 Snippet 工具生成代码片段的方式。两种方案的相同在于,通过简单的输入和选择就能获得预设后的项目代码。这种转化方式对于效率的提升效果是清晰可见的。于是有人就想到,能不能更进一步,将…

题目集7~8总结与分析

一.题目集七,7-1 家居强电电路模拟程序-3 1.前言 知识点考查和难度: 本题在上次迭代基础上增加了互斥开关和受控窗帘,以及电路的多并联。主要难度体现在互斥开关的引脚问题和通断特性。 更综合考查对设备的开关理解,和电路的逻辑结构。以及对电路设备的建立方式有些许的不…

再战博客园美化(七)

上回说到。。。我的博客总算有了一个亮色一个暗色主题可以切换了 里面也有一个forFlow?找不到文章列表,没有进行替换。 也行吧,以后再修,先埋雷先,反正我不是专业前端。(能跑不动原则) 今天玩——背景图!欧,不,丑死了。白天黑夜的图片需要不同 卡片半透明磨砂 标头、…

宋词300首获取

宋词三百首获取 近来一段时间无聊,突然被古诗词吸引,之后就有了后续的一系列操作 作为计算机专业,对于批量获取内容肯定首选🕷(仅供个人学习) 首先要有个目标,去哪个网站获取数据,这里就选择了页面简化的唐诗宋词.这里选择里面的宋词分支就好了 通过调用F12控制台会发现所有的…

416_前端工程化精讲

416_前端工程化精讲 //合并文档ds script 4357 || 已发布 || 开篇词 | 建立上帝视角,全面系统掌握前端效率工程化 || d6b0ec03a4374536a361909923c61bee 从事前端开发十余年 曾先后在多家大型互联网公司从事前端架构工作 讲师:李思嘉 贝壳找房前端架构组任资深工程师,…

java三阶段总结(家用电路模拟)

前言第六次题目集知识点:抽象类,抽象类不能被直接实例化!有抽象方法,抽象方法没有方法体,由继承它的子类提供具体实现。抽象类可以看作是一种模板,子类在实现接口方法时,必须实现接口中的所有抽象方法,除非子类也是抽象类在抽象类和接口中,多态体现为父类引用变量可以…

Material Design风格纯js确认框和对话框插件

material-modal是一款Material Design风格纯js确认框和对话框插件。该插件通过简单的CSS和JavaScript代码来构建确认框和对话框,是替代浏览器原生确认框和对话框的不错选择。在线预览 下载使用方法 在页面中引入material-modal.css和material-modal.js文件。< link rel=&…

PTA家居电路模拟3到家居模拟电路4

目录 一、答题判题程序第四次迭代 1、题目分析 2、题目类图 3、题目时序图 4、题目思路 二、家居强电电路模拟程序第一次迭代 1、题目分析 2、题目类图 3、题目时序图 4、题目思路 三、家居强电电路模拟程序第二次迭代 1、题目分析 2、题目类图 3、题目时序图 4、题目思路 四、…

Java难绷知识01——IO流的对象流

Java难绷知识01之对象流 本篇文章会探讨一些JavaIO流中比较容易被忽视的对象流,而且会相对的探讨其中的一些细节 其中对于对象流的操作讲解会少一些,主要讨论的是一些细节 在 Java IO 流中,对象流(ObjectInputStream对象输入流 和 ObjectOutputStream对象输出流)用于将对象…

题目集7-8总结

前言题目集的知识点、题量、难度 1.知识点总结:类的定义与实例化: 概念:定义类的属性和方法,创建对象 示例:public class Device { private String id; } 应用:定义各种电气设备类并创建实例继承关系: 概念:子类继承父类特征 示例:class Switch extends Device 应用:所…