Docker(四) Docker介绍

发布时间:2026/9/20 23:06:39
Docker(四) Docker介绍 Docker 是什么Docker 本质其实是 LXC 的增强版. 它本身不是容器, 并不实现虚拟化, 虚拟化仍然是利用 linux 内核的容器技术(namespace cgroup) 实现. Docker 是容器的易用工具, 它把容器的创建, 启动, 停止, 分发变得更加简单. Docker 在早期的版本其核心就是LXC 的二次封装发行版.Docker和LXC的区别是什么, LXC创建容器是借助LXC的template去创建, 而 Docker 发明了一个镜像技术, 把完整打包好的一个容器作为一个镜像放到仓库里, 然后当需要创建容器时, Docker 调用 LXC 的工具 lxc-create, 但不再通过 lxc 的模板去安装, 而是连接到镜像服务器上下载匹配的镜像文件, 而后基于镜像启动容器(就比如MYSQL官方把mysql程序写好打包存放到yum源的仓库, 然后我们yum install就可以安装mysql).所以, Docker 极大的简化了容器的使用难度. 以后我们创建启动容器, 只需要一个命令,docker-run,docker-stop就可以启动停止一个容器了.Docker 作为容器技术的一个实现, 或者说让容器技术普及开来的最成功的实现.Docker 是基于 Go 语言实现的一个开源项目, 它的主要目标是“Build Ship and Run Any APP Anywhere”, 即通过对组件的封装、分发、部署、运行等生命周期的管理使得用户的应用及其运行环境能够做到“一次封装到处运行”所以换句话来说, 我们普通的程序不能一次封装, 到处运行, 比如我们写好的java/cpp程序, 想要在centos或者ubuntu下运行, 会先发现我们缺失java/cpp运行环境, 就要先安装jdk/cpp标准库, 然后才能运行程序. 所以这一次封装不能到处运行.而镜像可以把OS相关依赖,运行环境依赖的库,应用程序文件及其配置文件全部封装起来.而docker是通过build-ship-run三步走来实现一次封装到处运行, 实现软件的封装, 分发, 部署和运行:Docker 的引擎迭代Docker 早期是基于LXC 容器管理引擎实现。当后来成熟之后, Docker为了打磨自己生态, 自建了一个容器引擎叫 libcontainer, 具备LXC的能力。后来谷歌和Docker大战以及 CNCF 的介入 Docker 公司将 Libcontainer 捐出, 并改名为了 runC成为工业化标准的容器引擎。目前所使用的新版 Docker所使用的容器引擎就是 RunC。Docker 和虚拟机的区别图1图2图3传统虚拟机Docker 容器原因磁盘占用几个 GB 到几十个 GB左右几十 MB 到几百 MB 左右如图1因为虚拟机保留了完整的Guest OS内核磁盘占用高Docker 共享了宿主机的OS内核CPU内存占用资源占用大资源利用率低。资源占用低资源利用率高如图1 虚拟机1.资源占用角度每个虚拟机都需要运行完整的 Guest OS会额外占用较多 CPU、内存等资源2.虚拟化开销角度虚拟机通过 Hypervisor 虚拟出完整的硬件环境存在一定虚拟化开销。这些资源并没有直接用于我们的业务程序属于额外开销所以相比于OS占用和虚拟化开销我们的应用可能只占用了少部分资源Docker1.资源占用角度容器本身就是一个进程不吃内存资源它与宿主机共享 Linux 内核不需要为每个容器运行独立 OS 内核只需运行应用及其用户态依赖。所以创建一个容器时不需要和虚拟机一样重新加载一个操作系统内核。从而避免引寻、加载操作系统内核返回时耗时耗资源的过程当新建一个虚拟机时虚拟机软件需要加载 Guest OS,返回新建过程是分钟级别的而新建一个docker 容器只需要几秒钟2.虚拟化开销角度容器比虚拟机有更少的抽象层它不经过Hypervisor虚拟化层可以直接和宿主OS交互使用实际物理机的硬件资源因此虚拟化开销低所以容器额外 CPU、内存开销较小资源利用率通常更高。启动速度从开机到运行项目几分钟几秒虚拟机启动要启动一个OS内核而容器只是启动一个进程安装管理需要专门的运维技术安装、管理方便传统虚拟机项目后面需要运维团队支持维护Docker通过Docker相关命令就能启动停止应用部署手动部署速度慢体系化部署可以自动化速度快如图2首先部署方面虚拟机部署可以直接把一个包含应用程序和系统运行环境的镜像打包部署镜像体积大速度慢也可以从下到上先安装OS运行环境再部署应用过程繁琐速度慢其次升级方面如果应用升级了jar从1.0升级到2.0 应用程序也升级了那需要手动去把新版本替换掉需要手动搬运的过程。而Docker部署如果应用是1.0 就把1.0的镜像推送到仓库如果是2.0也推送上去到时候部署的时候需要哪个就拉哪个而这些过程都可以通过docker命令实现把这些命令串起来就可以进行自动化部署速度快。隔离性系统级别进程级别虚拟机是系统级别隔离隔离等级比较低因为它把内核进行隔离安全性比较高Docker是进程级别隔离隔离级别高因为它没有隔离内核安全性低。封装程度打包整个操作系统打包项目代码和依赖信息Docker打包粒度比较低更精准Docker 和 JVM 虚拟化的区别Docker 版本Docker 发展过程中衍生了以下版本目前我们使用的版本是社区版docker-celxc上文中提到, lxc 是最早的 linux 容器技术, 早期版本的 docker 直接使用 lxc 来实现容器的底层功能。虽然使用者相对较少但 lxc 项目仍在持续开发演进中。但是如果docker一直依赖lxc作底层, docker的扩展性和生态构建比较困难, 所以自研了libcontainer.libcontainer docker 从 0.9 版本开始自行开发了 libcontainer 模块来作为 lxc 的替代品实现容器底层特性并在 1.10 版本彻底去除了 lxc。在 1.11 版本拆分出 runc 后libcontainer 也随之成为了 runc 的核心功能模块 runc 后续变成了容器标准。自此第一次容器大战Docker胜利。moby 第二次容器大战Google的K8s打败Docker的SwarmDocker把社区版Docker engine引流到企业版而社区版改名为moby。moby 是 docker 公司发起的开源项目其中最主要的部分就是同名组件 moby事实上这个 moby 就是 dockerd 目前使用的开源项目名称 docker 项目中的 enginedockerd仓库现在就是从 moby 仓库 fork 而来的使用 containerd 作为运行时标准。 官网https://mobyproject.org/docker-ce docker 的开源版本 CE 指 Community Edition。 docker-ce 中的组件来自于 moby、 containerd 等其他项目。 https://www.docker.com/pricing/docker-ee docker 的收费版本 EE 指 Enterprise Edition。其基础组件来源和docker-ce 是一样的但附加了一些其他的组件和功能。Docker 架构Docker 使用客户端-服务器 (C/S) 架构模式使用远程 API 来管理和创建 Docker 容器。Docker 容器通过 Docker 镜像来创建。Docker 仓库(Registry)Docker 仓库用来保存镜像就类似yum、apt仓库。 Docker Hub 供了庞大的镜像集合供使用。Docker daemonDocker daemon 是服务器组件是 Docker 最核心的后台进程我们也把它称为守护进程。Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker API 与 Docker 的守护进程通信。Docker 主机(Host)一个实际的物理服务器或者虚拟服务器, 用于执行 Docker 守护进程和容器。Docker 镜像(Images)Docker 镜像是用于创建 Docker 容器的模板。Docker 容器(Container)容器是独立运行的一个或一组应用。一个生活化的例子:有一天我(client)去华为旗舰店(Docker Host)买手机(client运行docker build一个image), 进门之后, 一个客服(docker deamon)来问我需要什么? 我说我要买华为手机, 客服说这个手机目前的展柜(Host里没有现成的镜像)里没有, 我去帮你到仓库(Registry)找一找(docker pull), 找到之后客服放回展柜, 我说你帮我开机验验机(docker run), 客服就把手机开机(此时image被运行起来成为一个container).Docker 生态新时代软件诉求在这里插入图片描述新时代软件诉求随着云计算、互联网和大规模分布式系统的发展软件运行环境发生了几个明显变化数据量极速增长物联网、云计算、边缘计算等技术的发展使需要处理的数据规模不断增大。根据 IDC 分布的《数据时代 2025》预测全球数据量将从 2018 年的 33ZB 增至 2025年的 175ZB增长超过 5 倍中国平均增速快于全球 3%预计到 2025 年将增至48.6ZB占全球数据圈的比例由 23.4%提升至 27.8%。其中中国企业级数据量将从2015 年占中国数据量的 49增长到 2025 年的 69。数据规模增大意味着物理上, 需要更多服务器软件上, 需要在大量服务器上部署软件, 软件部署和运维的规模越来越大。因此过去“手工登录服务器、手动安装软件”的方式逐渐无法满足需求, 体现在下面:计算资源规模快速增长企业的数据中心可能拥有成百上千甚至更多服务器。腾讯云全球服务器数量 100w数据量 EB 2020 年阿里云在全国已建成 5 大超级数据中心阿里云在全球 22个地域部署了上百个数据中心服务器的总规模数已经接近 200 万台。于是出现一个新问题如何快速、统一地把软件部署到大量服务器上如果每台服务器都手动执行yuminstall...wget...make... 修改配置文件 启动服务不仅效率低而且很容易出现不同服务器环境不一致的问题。软件需求爆发式增长研发模式从瀑布开发演变为敏捷开发原来 3 个月上一次新功能现在两周一次而开发过程中我们也经常遇到需要修改需求然后变更再发布的情况。软件上线有问题需要快速回滚对软件有着极强的版本管理和回滚诉求。因此软件系统产生了几个重要诉求快速发布, 快速部署版本管理, 出现问题时快速回滚。软件需要方便地共享软件开发完成之后不仅要在开发者自己的机器上运行还需要交付给测试人员, 运维人员, 其他开发者, 服务器集群。传统方式往往是代码 安装文档 依赖列表 配置文件接收者仍然需要自己重新搭建环境, 搭建环境期间就可能遇到许多各种各样的问题.因此希望能够将软件本身 运行软件所需要的环境一起交付。软件运行环境越来越复杂不同项目依赖的环境不同项目 A → Java 17 项目 B → Python 3.12 项目 C → GCC C 项目 D → Node.js甚至同一种语言也可能存在版本冲突项目 A → Python 3.8 项目 B → Python 3.12如果全部直接安装在宿主机上服务器 ├── Java ├── Python ├── GCC ├── Node.js ├── 各种动态库 └── 各种配置容易产生各种奇怪的问题, 比如依赖冲突, 版本冲突, 环境不一致等,运维复杂。这就是一个经典问题“在我电脑上明明可以运行为什么到了服务器就不能运行”Docker 要解决什么问题云时代需要我们针对这些诉求有一套针对的解决方案针对上面的问题, 可以把新时代的软件诉求概括成四个问题1. 我们要处理海量的数据如何处理呢 2. 软件需求上, 针对开发的需求需要频繁的变更上线如何才能将修改的代码快速的分发到几百或者 几千台服务器呢以及如何共享软件 3. 软件怎么进行版本管理和快速回滚 4. 不同的开发环境怎么搭建呢我们要处理海量的数据如何处理呢硬件上, 购买大量的服务器, 来具备数据处理的能力; 软件上, 研发对应软件来处理数据.软件如何分发到不同的服务器? 如何共享软件搞一个中心仓库让各个服务器去下载软件包安装, Docker Hub 是一个公共镜像仓库, 这样同一条 docker pull 命令下载的都是同样的软件:开发者 │ │ docker push ↓ 镜像仓库 │ │ docker pull ├─────────────┐ ↓ ↓ 服务器 A 服务器 B ↓ ↓ 运行容器 运行容器类比Linux也有软件仓库:Linux 软件 ↓ yum / apt 仓库 Docker 镜像 ↓ Docker Hub软件怎么进行版本管理和快速回滚Docker 设计了镜像, 将 docker 需要的所有信息设计一套软件格式, 把所有的依赖搞进去, 并打上版本标签 想用哪个版本就部署哪个版本想更换版本就关闭镜像A启动镜像B。镜像可以通过 Tag 管理版本myapp:v1.0 myapp:v1.1 myapp:v2.0软件升级v1.0 ↓ v2.0如果 v2.0 出现问题可以重新使用 v1.0, 实现快速回滚。不同的开发环境怎么搭建呢docker 设计了镜像来应对, 将应用程序 运行所需的用户态环境 依赖库 配置按照统一格式打包成Docker Image, 这其中就包含了相应的开发环境, 比如:myapp:v1.0 ├── 应用程序 ├── Python / Java / C runtime ├── 动态库 ├── 配置文件 └── 其他依赖总结一下:新时代 ↓ 服务器越来越多 ↓ 软件版本越来越多 ↓ 部署越来越频繁 ↓ 环境越来越复杂 ↓ 传统手工部署成本过高 ↓ 需要标准化软件交付方式 ↓ Docker Image ↓ 应用 依赖 用户态环境统一打包 ↓ 但镜像需要在机器之间传递 ↓ Image Registry ↓ Docker Hub / Harbor ↓ 大量服务器统一拉取镜像 ↓ 快速部署、升级、回滚