☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython
一、什么是容器
容器是一个标准化的单元,是一种轻量级、可移植的软件打包技术,容器将软件代码及其相关依赖打包,使应用程序可以在任何计算介质运行。例如开发人员在自己的机器上创建和运行的容器,几乎无须任何修改就可以在虚拟机、私有云、公有云、物理服务器等环境上运行。
容器主要支持Linux操作系统,因为Docker等容器技术的实现都是基于Linux内核的容器化技术。虽然Windows操作系统也支持容器化技术,但是相比Linux容器,Windows容器的应用范围和功能支持都相对有限。
在Linux系统中,容器技术已经得到了广泛应用和支持。几乎所有主流的Linux发行版都支持容器化技术,包括Ubuntu、CentOS、Debian等。此外,Docker等容器技术的实现也提供了对其他操作系统的支持,例如Mac和Windows等。
需要注意的是,不同的操作系统和容器技术可能会有一些特定的限制和差异,例如文件系统格式、网络配置、权限管理等。因此,在选择容器技术和操作系统时,需要根据实际需求和应用场景进行综合考虑。
二、容器的特性和优势
容器具有如下特点:
- 打包:将软件打包成标准化单元以进行开发、迁移和部署
- 隔离性:计算、存储、网络等资源彼此隔离
- 高效性:轻量、快速启停、快速部署与迁移
- 职责分工明确:开发专心写代码,运维专注基础环境配置
容器的优势:
- 对于开发人员: Build once, Run anywhere ,开发人员只需要构建一次应用运行环境,然后就可以将其打包成为容器以便在其他平台上运行。容器环境和宿主机环境完全隔离,又快速又简单
- 对于运维人员: Configure once, Run anything,运维人员只需要配置管理标准的runtime,就可以运行几乎所有容器。运维人员的工作高度一致和统一,效率高且可重复
三、容器和虚拟机的对比
容器只能使用 Host 的 kernel,并且不能修改。所有容器都共用 host 的 kernel,在容器中没办法对 kernel 升级。如果容器对 kernel 版本有要求(比如应用只能在某个 kernel 版本下运行),则不建议用容器,这种场景虚拟机可能更合适
3.1、容器和虚拟机的实现架构对比
下面这个图是容器和裸金属架构的虚拟机的实现逻辑架构对比图:
3.2、容器和虚拟机技术和应用特征对比
四、容器关键技术
容器的关键技术包括容器镜像管理和容器的网络管理。
4.1、镜像管理
4.1.1、什么是容器镜像
容器的镜像是指用于运行和启动容器的只读模板,容器镜像包含了容器运行时所需的程序、库、资源、配置等文件,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。容器镜像不包含任何动态数据,其内容在构建之后也不会被改变。容器是容器镜像的运行实例,容器运行时根据容器镜像创建容器。
相比于虚拟机的镜像,容器镜像更轻量化,它只是一个用户侧的rootfs。容器镜像是在容器里根目录上挂载的一个全新的文件系统,此文件系统与宿主机的文件系统无关,是一个完全独立的,用于给容器进行提供环境的文件系统。有了这个rootfs,容器就能够为进程构建出一个完整的文件系统,且实现了与宿主机的环境隔离。
4.1.2、镜像的分层管理
在介绍镜像的分层管理前,先有必要理解容器、镜像和linux内核之间的关系,不太清楚的同仁可以参考老猿在CSDN的博文《Docker容器镜像、Docker运行时用户空间和Linux内核之间的关系介绍》的介绍。
Docker镜像是采用分层方式构建和管理:
- 容器镜像由元数据和一层层的镜像构成,元数据主要描述镜像层之间的关系和容器的配置信息
- 通常构建 Docker 镜像时会以一个已存在的镜像或Scratch镜像为基础,在其上进行定制,这个已存在的镜像就是基础(base)镜像,关于与Scratch镜像请参考老猿在CSDN上的博文《信创之国产浪潮电脑+统信UOS操作系统体验8:安装Docker并进行测试验证scratch镜像》的介绍
- BASE镜像给用户提供一个基本的操作系统环境,然后在其上根据需求安装和配置上层软件
- 常见BASE镜像主要是各大Linux发行版的DOCKER镜像,如Ubuntu、CentOS等。BASE镜像不依赖其他镜像,从scratch构建。对于BASE镜像构建的容器来说,底层直接用Host的kernel,自己只需要提供rootfs就行了。其他镜像可以以base镜像为基础进行扩展。
当构建Docker镜像时,每条指令都会创建一个新的层,并将修改后的文件添加到这一层中。每个层都是只读的,它们可以被缓存和重复使用,而不需要每次都重新构建整个镜像。如果需要添加新的文件或更改现有文件,Docker会在新层上创建一个新的文件系统,并将需要更改的文件复制到新层中。同时可以将不同目录挂载到同一虚拟文件系统下。这种分层结构也使得镜像的修改和更新更加灵活和可控,因为只需要在需要修改的层中进行修改,而不会影响到其他层。
镜像分层最大的一个好处就是共享资源 ,比如:有多个镜像都从相同的 base 镜像构建而来,在仓库内或这本地磁盘上只需保存一份 base 镜像。那么 Docker Host 用这几个镜像在同一台机器上构建多个容器时,内存中只需加载一份 base镜像,就可以为所有容器服务了。
4.1.3、容器运行时的Copy-on-Write 特性
基于镜像的分层管理,如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc
是否也会被修改?答案是不会!
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“Container”即容器层,“容器层”之下的都叫“镜像层”。如图:
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的 ,因此容器的修改相互是隔离的。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统,在容器层中,用户看到的是一个叠加之后的文件系统。
下面深入讨论这种多层镜像+容器层的容器运行态中的文件操作机制:
- 文件读取:如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a
- 添加文件:在容器中创建文件时,新文件被添加到容器层中
- 修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后再执行修改
- 删除文件:由于每个镜像层都是只读的,因此不能直接删除镜像层中的文件,在容器中删除文件时,Docker会根据当前层和下面镜像层中是否存在该文件进行不同的处理。如果镜像层存在该文件,Docker会在容器层插入一个whiteout标记,用于遮盖文件,镜像层不处理。如果镜像层中不存在该文件,Docker会将文件从容器层中删除。
上述文件修改机制,只有当需要修改时才复制一份数据到容器层,这种特性被称作 Copy-on-Write。可见容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
4.2、Docker网络模式
4.2.1、Docker的网络模式设置
通过Docker创建时设定的network参数值来指定容器的网络模式,支持四种网络模式:
- bridge模式:这种模式是默认模式,容器拥有独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离,通过宿主机上的docker0网桥,与宿主机乃至外界进行网络通信,对于Docker的默认网络设置,一般使用Bridge模式
- host模式:容器和宿主机共享同一个网络命名空间,直接使用宿主机的ip和端口与外界通信
- none模式:Docker的None网络模式是一种不进行任何网络配置的网络模式。使用None模式,Docker容器拥有自己的Network Namespace,但是没有任何网络配置信息。在None模式下,容器无法进行网络连接,是一个封闭的网络环境。容器内的进程可以使用Lo网卡通信,Lo网卡是指本地回环网卡,也就是主机内网卡的回环映射
- 用户自定义模式(network=Network):docker1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络。
4.2.2、容器访问外部网络
4种网络模式下,容器对外部网络的访问支持能力是不一样的:
- Host模式:在Host模式下,容器与主机使用同一网络,因此可以直接通过主机的网络配置访问外部网络。
- Bridge模式:在Bridge模式下,容器通过网桥访问外网,访问时将源主机地址替换成宿主机的IP地址
- None模式:在None模式下,容器无法直接访问外部网络
- 自定义模式:在Network模式下,Docker可以创建自定义的网络,并将容器加入到该网络中。该网络可以配置IP地址、子网掩码、网关等网络参数,以实现容器访问外部网络。
4.2.3、外部网络访问容器
在Docker的Host和Bridge网络模式下,外部网络需要访问容器时,在运行容器时利用 -p[host port]:[container port]参数将容器对外提供服务的端口映射到宿主机的特定端口,外网通过访问宿主机的端口访问容器对外提供的服务。Docker每映射一个端口给宿主机端口,都会启动一个docker-proxy进程来处理对容器的访问数据流量。
五、Docker项目
- 简介
容器技术是基于容器引擎构建的打包技术,容器技术里面最典型的项目就是Docker,但并不是Docker就是容器技术的全部。
Docker是一个开源容器引擎,可以在Linux、Windows等平台上为任何应用创建一个轻量级、可移植的容器环境。
Docker项目由Docker公司用Go语言编写,遵循ApacheLicense2.0许可协议。
Docker公司的前身是dotCloud公司,2013年dotCloud公司开源了容器项目Docker。
Docker目前有两个版本: DockerCE(社区版本)和DockerEE(企业版本)。
-
Docker OCI(Open Container Initiative)规范
OCI规范是一种容器和镜像的标准和规范,旨在定义容器镜像的构建、打包、分发和运行等环节的统一标准。该规范由Docker、CoreOS、Google、RedHat等公司于2015年6月在Docker大会上共同宣布并随后成立OCI进行推动。
OCI规范包括两个主要部分:
√、Image Format Specification:容器镜像格式标准,规定应该以何种格式存储、分发镜像,dock image是docker容器的镜像,runtime根据dock image来创建容器,dockerfile是若干命令的文本文件,runtime可以根据这些命令创建出dock image
√、Runtime Specification:容器运行时标准,规定如何下载、解压缩、运行Filesystem Bundle。
任何符合OCI格式的镜像都可以在符合OCI标准的runtime之上工作。Docker v2镜像格式和runC成为了OCI的指定参考和实现规范。其中,Docker v2镜像格式捐给OCI作为镜像规范的基础,而runC则是Docker公司将libcontainer移动到后贡献给OCI作为容器运行时的参考实现。
OCI规范的出现使得不同平台、不同环境下的容器镜像可以相互移植,同时也方便了容器技术的推广和应用。 -
Docker架构
下图是Docker架构示意图:
从上图可以看出,Docker的架构包含了客户端Client、服务器端Docker Daemon、镜像Images、容器Containers和仓库Registry,其中服务器端Docker Daemon、镜像Images、容器Containers构成了Docker_Host。 -
Docker runtime是指Docker容器的真正运行环境。它是在容器启动时加载和运行可执行文件的地方,也是容器应用程序运行的环境。Docker runtime有多种实现方式,目前主流的三种容器runtime包括lxc、runc和rkt。其中,runc是Docker自己开发的runtime,也是目前Docker的默认runtime,符合oci规范。rkt是CoreOS开发的容器runtime,也符合oci规范,因此能够运行Docker的容器。
-
Docker的镜像仓库
Docker的镜像仓库叫Registry,是集中存放镜像的地方,可以方便后续的镜像拉取与上传,便于对镜像的集中管理。
镜像仓库一般可分为Docker Hub(http://hub.docker.com)公共中央仓库和个人或者公司使用的私有仓库。
- Docker Hub 是Docker公司面向公众开放的镜像托管仓库,是全球最大的镜像市场,目前已经有超过10w个容器镜像,大部分需求都可以通过在Docker Hub 中直接下载镜像来实现,方便开发者使用
- Docker Registry私有仓库是是Docker公司向个人用户提供的私有仓库,方便个人用户给使用
- Docker Harbor是Docker公司向企业级使用的私有镜像仓库。
六、小结
本文介绍了容器化技术的技术原理、特点优势以及容器的镜像管理和网络模式的关键技术,容器是镜像的运行时,同一主机运行的容器共用主机操作系统的内核,各容器将创建自己的用户空间,挂载rootfs文件系统。容器的文件系统来源于镜像,镜像分层管理,容器内的镜像层是只读的,对文件系统的更改通过在镜像层上面叠加container层来实现。
参考资料
1、Docker基础知识 (28) - 在 Dockerfile 中以 scratch 为基础镜像 (FROM scratch)
2、每天5分钟玩转 Docker 容器技术之镜像
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
更多云计算相关方面的介绍请参考《云计算与公有云服务》专栏的介绍。
关于老猿的付费专栏
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录 》
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。