Docker 入门:容器技术与 Docker 基础
本篇学习路线
为什么要容器(问题) → 容器是什么(概念) → 靠什么实现(原理) → 怎么发展到今天(历史)
→ 生态全貌 → Docker 架构 → 安装上手 → 镜像管理(第一个核心技能)
文章目录
- [Docker 入门:容器技术与 Docker 基础](#Docker 入门:容器技术与 Docker 基础)
- 一、为什么要容器?从一个真实的困境讲起
-
- [1.1 软件开发的"矩阵难题"](#1.1 软件开发的"矩阵难题")
- [1.2 集装箱的启示](#1.2 集装箱的启示)
-
- [集装箱思想 → 容器特性对照【重点】](#集装箱思想 → 容器特性对照【重点】)
- [1.3 容器对开发/运维分别意味着什么【重点】](#1.3 容器对开发/运维分别意味着什么【重点】)
- 二、容器到底是什么?
-
- [2.1 定义【重点】](#2.1 定义【重点】)
- [2.2 容器 vs 虚拟机:一张图看懂【重点】](#2.2 容器 vs 虚拟机:一张图看懂【重点】)
-
- [容器 vs 虚拟机对比表【重点,常考】](#容器 vs 虚拟机对比表【重点,常考】)
- [2.3 背景知识:容器之前的虚拟化方案](#2.3 背景知识:容器之前的虚拟化方案)
- 三、容器靠什么实现?两大内核基石【难点,务必理解】
- 四、容器发展简史【重点,了解来龙去脉】
-
-
- [4.1 一条主线看懂 40 年](#4.1 一条主线看懂 40 年)
- [4.2 各阶段详细脉络(知识点全表)](#4.2 各阶段详细脉络(知识点全表))
- [4.3 极简时间轴(建议背下来)【重点】](#4.3 极简时间轴(建议背下来)【重点】)
-
- 五、容器生态系统全貌
-
- [5.1 容器核心技术(六要素)](#5.1 容器核心技术(六要素))
-
- [① 容器规范(OCI)](#① 容器规范(OCI))
- [② 容器 runtime(运行时)](#② 容器 runtime(运行时))
- [③ 容器管理工具](#③ 容器管理工具)
- [④ 容器定义工具](#④ 容器定义工具)
- [⑤ Registry(镜像仓库)【重点】](#⑤ Registry(镜像仓库)【重点】)
- [⑥ 容器 OS](#⑥ 容器 OS)
- [5.2 容器平台技术(从单机到集群)](#5.2 容器平台技术(从单机到集群))
-
- [① 容器编排引擎【重点】](#① 容器编排引擎【重点】)
- [② 容器管理平台](#② 容器管理平台)
- [③ 基于容器的 PaaS](#③ 基于容器的 PaaS)
- [5.3 容器支持技术(周边保障)](#5.3 容器支持技术(周边保障))
- [六、Docker 是什么?](#六、Docker 是什么?)
-
- [6.1 定义【重点】](#6.1 定义【重点】)
- [6.2 Docker 架构【重点 + 难点】](#6.2 Docker 架构【重点 + 难点】)
-
- [① Client 客户端](#① Client 客户端)
- [② Docker Host 宿主机](#② Docker Host 宿主机)
- [③ Registry 镜像仓库](#③ Registry 镜像仓库)
- [④ 一次 `docker run nginx` 的完整流程【重点,考试常考】](#④ 一次
docker run nginx的完整流程【重点,考试常考】)
- [6.3 Docker 版本演变【了解】](#6.3 Docker 版本演变【了解】)
- [七、动手:安装 Docker 并跑起第一个容器](#七、动手:安装 Docker 并跑起第一个容器)
-
- [7.1 实验环境](#7.1 实验环境)
- [7.2 环境准备:搭建本地 yum 仓库(复习)](#7.2 环境准备:搭建本地 yum 仓库(复习))
- [7.3 防火墙与 Docker 仓库](#7.3 防火墙与 Docker 仓库)
- [7.4 安装并启动(allinone 部署)](#7.4 安装并启动(allinone 部署))
- [7.5 配置镜像加速【重点,国内必做】](#7.5 配置镜像加速【重点,国内必做】)
- [7.6 验证:跑起前两个容器](#7.6 验证:跑起前两个容器)
- [7.7 C/S 分离部署【难点:亲手验证 Docker 是 C/S 架构】](#7.7 C/S 分离部署【难点:亲手验证 Docker 是 C/S 架构】)
- [7.8 Docker 对 Windows 的支持](#7.8 Docker 对 Windows 的支持)
- [八、Docker 镜像管理(第一个核心技能)](#八、Docker 镜像管理(第一个核心技能))
-
- [8.0 先学会查帮助](#8.0 先学会查帮助)
- [8.1 search------查找镜像](#8.1 search——查找镜像)
-
- 查询镜像有哪些版本(tag)【重点,实操常需要】
- [查询 Harbor 私有仓库的镜像版本](#查询 Harbor 私有仓库的镜像版本)
- [8.2 pull------下载镜像【重点】](#8.2 pull——下载镜像【重点】)
- [8.3 ls------查看本地镜像列表](#8.3 ls——查看本地镜像列表)
- [8.4 tag------给镜像打标签](#8.4 tag——给镜像打标签)
-
- [tag 的最佳实践:滚动版本号方案【重点】](#tag 的最佳实践:滚动版本号方案【重点】)
- [8.5 inspect------查看镜像详细信息](#8.5 inspect——查看镜像详细信息)
- [8.6 history------查看镜像的"分层历史"](#8.6 history——查看镜像的"分层历史")
- [8.7 rm------删除镜像【重点 + 易错】](#8.7 rm——删除镜像【重点 + 易错】)
- [8.8 prune------批量清理镜像](#8.8 prune——批量清理镜像)
- [8.9 save / load------镜像的离线导出与导入【重点】](#8.9 save / load——镜像的离线导出与导入【重点】)
- [8.10 push------把本地镜像推送到仓库](#8.10 push——把本地镜像推送到仓库)
- 本篇知识自测清单
一、为什么要容器?从一个真实的困境讲起
1.1 软件开发的"矩阵难题"
现代应用很少是"一个程序跑起来"这么简单:
- 一个应用往往由多种服务组装而成:消息队列(MQ)、缓存(Cache)、数据库(DB)......每个服务都有自己的依赖库、软件包、配置;
- 应用还要部署到多种环境:虚拟服务器、私有云、公有云......
于是产生了一个核心矛盾------如何让每种服务在所有环境里都顺利运行?
服务 × 环境,排列组合,形成一个 N×M 的大矩阵:
#mermaid-svg-x0jHabgV6wD5xXyW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x0jHabgV6wD5xXyW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x0jHabgV6wD5xXyW .error-icon{fill:#552222;}#mermaid-svg-x0jHabgV6wD5xXyW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x0jHabgV6wD5xXyW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x0jHabgV6wD5xXyW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x0jHabgV6wD5xXyW .marker.cross{stroke:#333333;}#mermaid-svg-x0jHabgV6wD5xXyW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x0jHabgV6wD5xXyW p{margin:0;}#mermaid-svg-x0jHabgV6wD5xXyW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-x0jHabgV6wD5xXyW .cluster-label text{fill:#333;}#mermaid-svg-x0jHabgV6wD5xXyW .cluster-label span{color:#333;}#mermaid-svg-x0jHabgV6wD5xXyW .cluster-label span p{background-color:transparent;}#mermaid-svg-x0jHabgV6wD5xXyW .label text,#mermaid-svg-x0jHabgV6wD5xXyW span{fill:#333;color:#333;}#mermaid-svg-x0jHabgV6wD5xXyW .node rect,#mermaid-svg-x0jHabgV6wD5xXyW .node circle,#mermaid-svg-x0jHabgV6wD5xXyW .node ellipse,#mermaid-svg-x0jHabgV6wD5xXyW .node polygon,#mermaid-svg-x0jHabgV6wD5xXyW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x0jHabgV6wD5xXyW .rough-node .label text,#mermaid-svg-x0jHabgV6wD5xXyW .node .label text,#mermaid-svg-x0jHabgV6wD5xXyW .image-shape .label,#mermaid-svg-x0jHabgV6wD5xXyW .icon-shape .label{text-anchor:middle;}#mermaid-svg-x0jHabgV6wD5xXyW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x0jHabgV6wD5xXyW .rough-node .label,#mermaid-svg-x0jHabgV6wD5xXyW .node .label,#mermaid-svg-x0jHabgV6wD5xXyW .image-shape .label,#mermaid-svg-x0jHabgV6wD5xXyW .icon-shape .label{text-align:center;}#mermaid-svg-x0jHabgV6wD5xXyW .node.clickable{cursor:pointer;}#mermaid-svg-x0jHabgV6wD5xXyW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x0jHabgV6wD5xXyW .arrowheadPath{fill:#333333;}#mermaid-svg-x0jHabgV6wD5xXyW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x0jHabgV6wD5xXyW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x0jHabgV6wD5xXyW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x0jHabgV6wD5xXyW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x0jHabgV6wD5xXyW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x0jHabgV6wD5xXyW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x0jHabgV6wD5xXyW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x0jHabgV6wD5xXyW .cluster text{fill:#333;}#mermaid-svg-x0jHabgV6wD5xXyW .cluster span{color:#333;}#mermaid-svg-x0jHabgV6wD5xXyW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x0jHabgV6wD5xXyW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x0jHabgV6wD5xXyW rect.text{fill:none;stroke-width:0;}#mermaid-svg-x0jHabgV6wD5xXyW .icon-shape,#mermaid-svg-x0jHabgV6wD5xXyW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x0jHabgV6wD5xXyW .icon-shape p,#mermaid-svg-x0jHabgV6wD5xXyW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x0jHabgV6wD5xXyW .icon-shape .label rect,#mermaid-svg-x0jHabgV6wD5xXyW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x0jHabgV6wD5xXyW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x0jHabgV6wD5xXyW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x0jHabgV6wD5xXyW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 要部署到多种环境
应用包含多种服务
MQ 服务
Cache 服务
DB 服务
虚拟服务器
私有云
公有云
对开发人员:写代码要考虑不同运行环境;对运维人员:要为每种服务 × 每种平台配置环境。双方都是灾难。
典型场景你一定见过:"在我电脑上明明能跑啊?"------开发环境好好的,一到测试/生产环境就报"缺依赖库"、"版本不对"、"配置丢了"。这就是环境不一致问题。
1.2 集装箱的启示
几十年前,运输业遇到过一模一样的问题:
- 不同货物混装会互相损坏(铁桶压坏香蕉);
- 货物要在卡车、轮船、火车之间反复装卸,一半以上时间花在装/卸货上,还容易损坏货物。
这同样是一个 N×M 矩阵(货物 × 交通工具)。
集装箱的发明解决了这一切:任何货物装进标准集装箱,全程密封、只在目的地开箱;标准化的接口让集装箱在卡车、轮船、火车之间高效转运,无需开箱。集装箱被誉为运输业与世界贸易最重要的发明。
Docker 做的事,就是把"集装箱思想"搬到软件领域:把任何应用连同它的依赖打包成一个轻量级、可移植、自包含的"集装箱"(容器),可以在几乎所有操作系统上运行。
"集装箱"和"容器"的英文都是 Container。"容器"是国内软件领域约定俗成的叫法。
集装箱思想 → 容器特性对照【重点】
| 特性 | 集装箱 | 容器 |
|---|---|---|
| 打包对象 | 几乎任何货物 | 任何软件及其依赖 |
| 硬件依赖 | 标准形状接口,可装卸到任何交通工具,全程不开箱 | 无需修改即可运行在几乎所有平台(虚拟机、物理机、公有云、私有云) |
| 隔离性 | 集装箱可堆叠运输,货物互不干扰 | 资源、网络、库都是隔离的,不会出现依赖冲突 |
| 自动化 | 标准接口便于自动装卸 | 提供 run/start/stop 等标准化操作,适合自动化 |
| 高效性 | 无需开箱即可快速转运 | 轻量级,能快速启动和迁移 |
| 职责分工 | 货主只管装什么,承运方只管怎么运 | 开发只管写代码,运维只管配基础环境 |
1.3 容器对开发/运维分别意味着什么【重点】
两个口号记住容器的好处:
- 对开发人员 ------Build Once, Run Anywhere(一次构建,到处运行):只需为应用创建一次运行环境,打包成容器后可在任何机器上运行;容器环境与宿主机隔离,像虚拟机一样隔离,但更快更简单。
- 对运维人员 ------Configure Once, Run Anything(一次配置,运行一切):只需配好标准的 runtime 环境,服务器就能运行任何容器;开发、测试、生产环境高度一致,工作变得高效、可重复。
二、容器到底是什么?
2.1 定义【重点】
容器 = 操作系统级虚拟化技术 :在同一台宿主机操作系统之上,把应用程序 + 依赖库 + 配置文件 + 环境变量打包在一起,形成相互隔离的运行环境。
关键词"操作系统级":容器不需要携带一个完整的操作系统,它直接共享宿主机的 OS 内核,只打包"应用 + 它需要的环境"。
2.2 容器 vs 虚拟机:一张图看懂【重点】
传统虚拟化(VMware、KVM、Xen)的目标是创建完整的虚拟机。为了运行一个几十 MB 的应用,你得先在虚拟机里装一套几十 GB 的操作系统。
虚拟机架构------每个应用背一个完整 OS:
#mermaid-svg-pdLDh0RbnNMGevgR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pdLDh0RbnNMGevgR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pdLDh0RbnNMGevgR .error-icon{fill:#552222;}#mermaid-svg-pdLDh0RbnNMGevgR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pdLDh0RbnNMGevgR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pdLDh0RbnNMGevgR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pdLDh0RbnNMGevgR .marker.cross{stroke:#333333;}#mermaid-svg-pdLDh0RbnNMGevgR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pdLDh0RbnNMGevgR p{margin:0;}#mermaid-svg-pdLDh0RbnNMGevgR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pdLDh0RbnNMGevgR .cluster-label text{fill:#333;}#mermaid-svg-pdLDh0RbnNMGevgR .cluster-label span{color:#333;}#mermaid-svg-pdLDh0RbnNMGevgR .cluster-label span p{background-color:transparent;}#mermaid-svg-pdLDh0RbnNMGevgR .label text,#mermaid-svg-pdLDh0RbnNMGevgR span{fill:#333;color:#333;}#mermaid-svg-pdLDh0RbnNMGevgR .node rect,#mermaid-svg-pdLDh0RbnNMGevgR .node circle,#mermaid-svg-pdLDh0RbnNMGevgR .node ellipse,#mermaid-svg-pdLDh0RbnNMGevgR .node polygon,#mermaid-svg-pdLDh0RbnNMGevgR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pdLDh0RbnNMGevgR .rough-node .label text,#mermaid-svg-pdLDh0RbnNMGevgR .node .label text,#mermaid-svg-pdLDh0RbnNMGevgR .image-shape .label,#mermaid-svg-pdLDh0RbnNMGevgR .icon-shape .label{text-anchor:middle;}#mermaid-svg-pdLDh0RbnNMGevgR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pdLDh0RbnNMGevgR .rough-node .label,#mermaid-svg-pdLDh0RbnNMGevgR .node .label,#mermaid-svg-pdLDh0RbnNMGevgR .image-shape .label,#mermaid-svg-pdLDh0RbnNMGevgR .icon-shape .label{text-align:center;}#mermaid-svg-pdLDh0RbnNMGevgR .node.clickable{cursor:pointer;}#mermaid-svg-pdLDh0RbnNMGevgR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pdLDh0RbnNMGevgR .arrowheadPath{fill:#333333;}#mermaid-svg-pdLDh0RbnNMGevgR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pdLDh0RbnNMGevgR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pdLDh0RbnNMGevgR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pdLDh0RbnNMGevgR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pdLDh0RbnNMGevgR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pdLDh0RbnNMGevgR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pdLDh0RbnNMGevgR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pdLDh0RbnNMGevgR .cluster text{fill:#333;}#mermaid-svg-pdLDh0RbnNMGevgR .cluster span{color:#333;}#mermaid-svg-pdLDh0RbnNMGevgR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pdLDh0RbnNMGevgR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pdLDh0RbnNMGevgR rect.text{fill:none;stroke-width:0;}#mermaid-svg-pdLDh0RbnNMGevgR .icon-shape,#mermaid-svg-pdLDh0RbnNMGevgR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pdLDh0RbnNMGevgR .icon-shape p,#mermaid-svg-pdLDh0RbnNMGevgR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pdLDh0RbnNMGevgR .icon-shape .label rect,#mermaid-svg-pdLDh0RbnNMGevgR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pdLDh0RbnNMGevgR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pdLDh0RbnNMGevgR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pdLDh0RbnNMGevgR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用A
来宾操作系统
(几十GB)
应用B
来宾操作系统
(几十GB)
Hypervisor 虚拟化层
宿主机操作系统
物理硬件
容器架构------所有容器共享同一个宿主机 OS 内核:
#mermaid-svg-PnGV2OgMGunqpUnu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PnGV2OgMGunqpUnu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PnGV2OgMGunqpUnu .error-icon{fill:#552222;}#mermaid-svg-PnGV2OgMGunqpUnu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PnGV2OgMGunqpUnu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PnGV2OgMGunqpUnu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PnGV2OgMGunqpUnu .marker.cross{stroke:#333333;}#mermaid-svg-PnGV2OgMGunqpUnu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PnGV2OgMGunqpUnu p{margin:0;}#mermaid-svg-PnGV2OgMGunqpUnu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PnGV2OgMGunqpUnu .cluster-label text{fill:#333;}#mermaid-svg-PnGV2OgMGunqpUnu .cluster-label span{color:#333;}#mermaid-svg-PnGV2OgMGunqpUnu .cluster-label span p{background-color:transparent;}#mermaid-svg-PnGV2OgMGunqpUnu .label text,#mermaid-svg-PnGV2OgMGunqpUnu span{fill:#333;color:#333;}#mermaid-svg-PnGV2OgMGunqpUnu .node rect,#mermaid-svg-PnGV2OgMGunqpUnu .node circle,#mermaid-svg-PnGV2OgMGunqpUnu .node ellipse,#mermaid-svg-PnGV2OgMGunqpUnu .node polygon,#mermaid-svg-PnGV2OgMGunqpUnu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PnGV2OgMGunqpUnu .rough-node .label text,#mermaid-svg-PnGV2OgMGunqpUnu .node .label text,#mermaid-svg-PnGV2OgMGunqpUnu .image-shape .label,#mermaid-svg-PnGV2OgMGunqpUnu .icon-shape .label{text-anchor:middle;}#mermaid-svg-PnGV2OgMGunqpUnu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PnGV2OgMGunqpUnu .rough-node .label,#mermaid-svg-PnGV2OgMGunqpUnu .node .label,#mermaid-svg-PnGV2OgMGunqpUnu .image-shape .label,#mermaid-svg-PnGV2OgMGunqpUnu .icon-shape .label{text-align:center;}#mermaid-svg-PnGV2OgMGunqpUnu .node.clickable{cursor:pointer;}#mermaid-svg-PnGV2OgMGunqpUnu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PnGV2OgMGunqpUnu .arrowheadPath{fill:#333333;}#mermaid-svg-PnGV2OgMGunqpUnu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PnGV2OgMGunqpUnu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PnGV2OgMGunqpUnu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PnGV2OgMGunqpUnu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PnGV2OgMGunqpUnu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PnGV2OgMGunqpUnu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PnGV2OgMGunqpUnu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PnGV2OgMGunqpUnu .cluster text{fill:#333;}#mermaid-svg-PnGV2OgMGunqpUnu .cluster span{color:#333;}#mermaid-svg-PnGV2OgMGunqpUnu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PnGV2OgMGunqpUnu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PnGV2OgMGunqpUnu rect.text{fill:none;stroke-width:0;}#mermaid-svg-PnGV2OgMGunqpUnu .icon-shape,#mermaid-svg-PnGV2OgMGunqpUnu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PnGV2OgMGunqpUnu .icon-shape p,#mermaid-svg-PnGV2OgMGunqpUnu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PnGV2OgMGunqpUnu .icon-shape .label rect,#mermaid-svg-PnGV2OgMGunqpUnu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PnGV2OgMGunqpUnu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PnGV2OgMGunqpUnu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PnGV2OgMGunqpUnu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用A + 环境
共享宿主机
操作系统内核
应用B + 环境
应用C + 环境
宿主机操作系统
物理硬件
由此带来三个关键特点:
- 所有容器共享同一个 Host OS,所以体积远小于虚拟机;
- 启动容器不需要启动整个操作系统------部署和启动速度更快、开销更小、更容易迁移;
- 容器内程序直接在 CPU 上本地运行指令,不需要虚拟化那套"指令级模拟"或"即时编译",所以性能接近原生。
容器 vs 虚拟机对比表【重点,常考】
| 特性 | 容器 | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 性能 | 接近原生 | 较弱 |
| 内存代价 | 很小 | 较多 |
| 硬盘使用 | 一般为 MB | 一般为 GB |
| 运行密度 | 单机支持上千个容器 | 一般几十个 |
| 隔离性 | 安全隔离 | 完全隔离 |
| 迁移性 | 优秀 | 一般 |
注意"隔离性"一栏:虚拟机是完全隔离 (各自独立内核),容器只是安全隔离(共享内核,靠内核机制隔离)------这也是容器比虚拟机轻的原因,同时是容器隔离性弱于虚拟机的原因。
2.3 背景知识:容器之前的虚拟化方案
学习容器前,先了解业界曾经/正在使用的虚拟化方案(本课程前情提要):
| 方案 | 说明 |
|---|---|
| VMware Workstation | 个人桌面级虚拟机软件 |
| KVM + oVirt | KVM 是 Linux 内核自带的虚拟化技术;oVirt 用于集中管理多台 KVM 虚拟主机 |
| VMware ESXi + vCenter | 企业级裸金属虚拟化 + 集中管理平台 |
| OpenStack(nova 组件) | 开源私有云平台;nova 是计算核心,包含 nova-api、nova-scheduler、nova-compute |
它们解决的是"一台物理机当多台用"的问题;容器解决的则是"应用打包与环境一致性"问题,二者定位不同。
三、容器靠什么实现?两大内核基石【难点,务必理解】
容器不是凭空出现的魔法,它完全依赖 Linux 内核提供的两个机制:
Namespace(命名空间)负责"隔离"------让容器之间互相看不见;
Cgroups(控制组)负责"限制"------让容器之间互相不抢占。
Namespace:让容器"各自为政"
| Namespace | 隔离什么 | 效果 |
|---|---|---|
| PID | 进程编号 | 容器内有自己的 PID 1、PID 2......看不到宿主机进程 |
| Network | 网络栈 | 每个容器有独立的网卡、IP、路由表 |
| IPC | 进程间通信 | 容器间信号量、共享内存互不干扰 |
| Mount | 挂载点 | 容器有独立的文件系统挂载视图 |
| User | 用户 UID/GID | 容器内的 root ≠ 宿主机的 root,解决容器权限安全问题 |
| UTS | 主机名 | 容器可有独立的主机名(如 -h myos) |
Cgroups:给容器"上配额"
由 Google 工程师开发,能对容器的 CPU、内存、IO、网络带宽做限制------容器 A 再忙也不能吃光宿主机资源。
记住这个等式(贯穿整个 Docker 学习):
容器 = 应用 + 环境打包 +(Namespace 隔离 + Cgroups 资源限制)
容器本质上是宿主机上受管控的普通进程,而不是虚拟机。
四、容器发展简史【重点,了解来龙去脉】
4.1 一条主线看懂 40 年
#mermaid-svg-7QR4bLi8lBlksKyJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7QR4bLi8lBlksKyJ .error-icon{fill:#552222;}#mermaid-svg-7QR4bLi8lBlksKyJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7QR4bLi8lBlksKyJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7QR4bLi8lBlksKyJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7QR4bLi8lBlksKyJ .marker.cross{stroke:#333333;}#mermaid-svg-7QR4bLi8lBlksKyJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7QR4bLi8lBlksKyJ p{margin:0;}#mermaid-svg-7QR4bLi8lBlksKyJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster-label text{fill:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster-label span{color:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster-label span p{background-color:transparent;}#mermaid-svg-7QR4bLi8lBlksKyJ .label text,#mermaid-svg-7QR4bLi8lBlksKyJ span{fill:#333;color:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ .node rect,#mermaid-svg-7QR4bLi8lBlksKyJ .node circle,#mermaid-svg-7QR4bLi8lBlksKyJ .node ellipse,#mermaid-svg-7QR4bLi8lBlksKyJ .node polygon,#mermaid-svg-7QR4bLi8lBlksKyJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7QR4bLi8lBlksKyJ .rough-node .label text,#mermaid-svg-7QR4bLi8lBlksKyJ .node .label text,#mermaid-svg-7QR4bLi8lBlksKyJ .image-shape .label,#mermaid-svg-7QR4bLi8lBlksKyJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-7QR4bLi8lBlksKyJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7QR4bLi8lBlksKyJ .rough-node .label,#mermaid-svg-7QR4bLi8lBlksKyJ .node .label,#mermaid-svg-7QR4bLi8lBlksKyJ .image-shape .label,#mermaid-svg-7QR4bLi8lBlksKyJ .icon-shape .label{text-align:center;}#mermaid-svg-7QR4bLi8lBlksKyJ .node.clickable{cursor:pointer;}#mermaid-svg-7QR4bLi8lBlksKyJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7QR4bLi8lBlksKyJ .arrowheadPath{fill:#333333;}#mermaid-svg-7QR4bLi8lBlksKyJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7QR4bLi8lBlksKyJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7QR4bLi8lBlksKyJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7QR4bLi8lBlksKyJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7QR4bLi8lBlksKyJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7QR4bLi8lBlksKyJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster text{fill:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ .cluster span{color:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7QR4bLi8lBlksKyJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7QR4bLi8lBlksKyJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-7QR4bLi8lBlksKyJ .icon-shape,#mermaid-svg-7QR4bLi8lBlksKyJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7QR4bLi8lBlksKyJ .icon-shape p,#mermaid-svg-7QR4bLi8lBlksKyJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7QR4bLi8lBlksKyJ .icon-shape .label rect,#mermaid-svg-7QR4bLi8lBlksKyJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7QR4bLi8lBlksKyJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7QR4bLi8lBlksKyJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7QR4bLi8lBlksKyJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1979
chroot
文件系统隔离
1998-2000
Jails / Zones
完整OS级隔离
2002-2008
Namespace + Cgroups
陆续进入 Linux 内核
2008
LXC
第一个Linux容器工具
2013
Docker
镜像+Dockerfile 容器大众化
2015
OCI标准 + K8s 1.0
标准化+集群编排
2016至今
runc/containerd/CRI
云原生生态成熟
4.2 各阶段详细脉络(知识点全表)
阶段一:早期隔离思想(各 Unix 系统各自实现,Linux 尚无原生方案)
| 时间 | 事件 | 要点 |
|---|---|---|
| 1979 | Unix V7 引入 chroot() 系统调用 |
修改进程根目录,实现文件系统隔离;只有目录隔离,没有 CPU/内存/网络隔离,是容器最早的技术原型 |
| 1998 | FreeBSD Jails | 在 chroot 基础上增加进程、网络隔离,一台主机可跑多个独立"虚拟系统",现代容器思想的重要实践 |
| 2000 | Solaris Zones | 操作系统级虚拟化,CPU/内存/网络/文件系统完整隔离(Oracle 商用方案) |
知识拓展:
chroot至今仍有个经典用途------破解 Linux root 密码 (救援模式挂载真实根后chroot进去改密码):
bash/dev/centos/root /mnt/sysroot mount -o rw,remount /mnt/sysroot chroot /mnt/sysroot/
阶段二:Linux 内核关键技术就位(容器底层能力逐渐完备)
| 时间 | 技术 | 作用 |
|---|---|---|
| 2002 | PID Namespace 进内核 | 进程 ID 隔离 |
| 2003 | Network Namespace 进内核 | 网络栈隔离 |
| 2004--2006 | IPC、Mount Namespace 陆续合入 | 进程间通信隔离、挂载点隔离 |
| 2007 | Cgroups 合入 Linux 内核 | CPU/内存/IO/网络带宽资源限制(Google 工程师开发) |
| 2008 | User Namespace 开始开发迭代 | UID/GID 隔离,容器内 root ≠ 宿主机 root;后续版本逐步完善 |
阶段三:LXC 容器诞生
| 时间 | 事件 |
|---|---|
| 2008 | **LXC(Linux Containers)**项目启动:基于 Namespace + Cgroups 封装,世界上第一个完整的 Linux 用户态容器工具。痛点:没有镜像机制、配置复杂、分发困难,主要面向运维专家 |
| 2010 | VMware 推出 CloudFoundry Warden:容器管理服务,做资源隔离与实例生命周期管理 |
| 2013 | PaaS 云厂商 dotCloud 内部孵化 Docker,专门解决 LXC 的镜像、打包、分发痛点 |
阶段四:Docker 爆发
| 时间 | 事件 | 意义 |
|---|---|---|
| 2013-06 | Docker 0.1 发布(基于 LXC) | 核心创新:镜像分层、Dockerfile、镜像仓库、统一工具链 ------容器不再只是隔离工具,而是完整的应用打包分发体系,迅速出圈 |
| 2014-06 | Docker 1.0 发布 | 宣布生产可用;Docker Hub 公共镜像仓库大规模使用 |
| 2014 | Google 发布 Borg 论文 | Borg 是 Google 内部大规模容器调度系统,是 Kubernetes 的思想源头;同期 Google 放出 lmctfy 容器工具 |
| 2014-07 | Docker 切换到自研 libcontainer | 抛弃 LXC,直接调用 Linux 系统调用,不依赖 LXC 工具链,容器运行时走向独立 |
| 2015-06 | OCI(Open Container Initiative)成立 | Linux 基金会主导,Docker、Google、红帽等共同成立,制定容器镜像规范 + 容器运行时规范,避免容器生态分裂 |
阶段五:Kubernetes 崛起与运行时分层
| 时间 | 事件 | 意义 |
|---|---|---|
| 2015-07 | Kubernetes 1.0 发布 | Google 基于 Borg 经验开源 K8s,实现调度、自愈、服务发现、滚动更新------容器从单机走向大规模集群 |
| 2016 | runc 发布 | libcontainer 改名 runc,OCI 标准运行时,底层真正创建容器的工具,Docker 底层调用它 |
| 2016 | containerd 诞生 | Docker 拆分出的高级容器运行时,管理镜像和容器生命周期;上层对接 docker/k8s,下层调用 runc |
| 2017 | K8s 移交 CNCF(云原生计算基金会)托管 | K8s 成为容器编排事实标准;Docker 公司商业受挫,其编排引擎 Docker Swarm 逐渐边缘化 |
| 2017--2018 | CRI(容器运行时接口)成熟 | K8s 定义 CRI 接口,不再强绑定 Docker;cri-containerd 把 containerd 适配进 CRI |
阶段六:云原生生态成熟
- K8s 移除 dockershim:K8s 不再内置 Docker 适配层,containerd 成为 K8s 默认容器运行时;Docker 保留为开发工具,在集群层面不再是首选运行时。
- 安全容器:Kata Containers(轻量级虚拟机、内核隔离、强安全隔离)、gVisor(Google 用户态内核,把应用与宿主机内核隔开)。
- 其他 OCI 兼容运行时:nerdctl(containerd 的命令行工具,兼容 docker 命令)、crun(C 语言实现的轻量 runc 替代品)。
- 2020--2023 :红帽 Podman + Buildah 普及------无守护进程、兼容 docker 命令、原生支持 OCI 标准。
- 2024--2026:WebAssembly 容器兴起(Wasm-OCI,把 Wasm 当镜像,开销极低),K8s 对 Wasm 运行时支持增强。
4.3 极简时间轴(建议背下来)【重点】
| 时间 | 里程碑 | 核心价值 |
|---|---|---|
| 1979 | Unix chroot | 文件系统隔离原型 |
| 1998 | FreeBSD Jails | 完整 OS 级隔离雏形 |
| 2007 | Linux Cgroups 合入内核 | 资源限制基石 |
| 2008 | LXC 项目诞生 | 第一个 Linux 容器工具 |
| 2013 | Docker 发布 | 镜像 + Dockerfile,容器大众化 |
| 2015 | OCI 成立;K8s 1.0 | 标准化 + 集群编排时代开启 |
| 2016 | runc、containerd | 分层容器运行时架构 |
| 2017 | K8s 移交 CNCF | K8s 成为编排事实标准 |
| 2022 | K8s 彻底移除 dockershim | containerd 成为 K8s 默认运行时 |
| 2023 至今 | Wasm 容器、安全容器 | 轻量、强隔离新方向 |
【难点补充】为什么 runc、containerd 这一层很重要?可以把容器运行时想象成"厨房分工":
- runc:真正点火的厨师(创建/销毁单个容器);
- containerd:厨房主管(管理镜像、容器生命周期、日志);
- docker/k8s :点菜的前台(面向用户的界面)。
K8s 通过 CRI 标准接口"点菜",所以换不换 Docker 它都无所谓。
五、容器生态系统全貌
容器不只是 Docker 一个工具,而是一整片生态。分三层看:核心技术 (单机能跑容器)、平台技术 (集群规模编排)、支持技术(周边保障)。
5.1 容器核心技术(六要素)
① 容器规范(OCI)
容器不只有 Docker(还有 CoreOS 的 rkt 等)。为保证不同容器互相兼容,Docker、CoreOS、Google 等公司共同成立 OCI,发布了两个规范:
- runtime spec:容器运行环境规范(runtime 是容器运行的环境);
- image format spec:镜像格式规范(image = 应用 + 依赖库 + 配置 + 环境变量的打包文件)。
有了规范,不同组织/厂商的容器可以在不同 runtime 上运行------可移植性和互操作性。
② 容器 runtime(运行时)
runtime 与操作系统内核紧密协作,为容器提供运行环境。主流三种:
| runtime | 说明 |
|---|---|
| lxc | Linux 老牌 runtime,Docker 最初就用它 |
| runc | Docker 自研 ,符合 OCI 规范,现在 Docker 的默认 runtime |
| rkt | CoreOS 开发,符合 OCI 规范,因此也能运行 Docker 的容器 |
③ 容器管理工具
光有 runtime 不够------用户需要工具来操作容器。管理工具对内与 runtime 交互,对外给用户提供 CLI。
类比:有了 JVM 还不行,还得有 java 命令让你能启动程序。
| runtime | 管理工具 |
|---|---|
| lxc | lxd |
| runc | docker engine(含后台 daemon + CLI 两部分;我们平时说的 "Docker" 就是指它) |
| rkt | rkt cli |
④ 容器定义工具
用来定义容器的内容和属性,让容器能被保存、共享、重建:
- docker image:Docker 容器的模板,runtime 依据它创建容器;
- dockerfile:包含若干命令的文本文件,通过这些命令能构建出 docker image(后面课程的重点);
- ACI(App Container Image):CoreOS 为 rkt 开发的镜像格式,与 docker image 类似。
⑤ Registry(镜像仓库)【重点】
容器由 image 创建,image 需要统一存放的地方------就是 Registry:
- 企业可以用 Docker Registry 搭建私有仓库;
- Docker Hub(https://hub.docker.com):官方公共托管仓库,有大量现成镜像,对用户极其方便;
- Quay.io(https://quay.io):另一个公共托管仓库。
⑥ 容器 OS
因为有容器 runtime,几乎所有的 Linux、macOS、Windows 都能跑容器。容器 OS 是专门为运行容器定制的操作系统:体积更小、启动更快、运行容器效率更高。代表:CoreOS、atomic、ubuntu core。
5.2 容器平台技术(从单机到集群)
核心技术只解决"单机跑容器";平台技术让容器作为集群在分布式环境运行。
① 容器编排引擎【重点】
基于容器的应用一般采用微服务架构:
- 应用被拆分成不同组件,各自以服务形式跑在容器里,通过 API 对外提供服务;
- 为了高可用,每个组件可能跑多个相同容器组成集群,容器根据业务动态创建、迁移、销毁。
这样一个动态可伸缩的系统,靠人工管理不现实------这就是**编排(Orchestration)**要干的事:容器管理、调度、集群定义、服务发现。主流引擎:
- Docker Swarm:Docker 自家编排引擎;
- Kubernetes:Google 主导的开源编排引擎,同时支持 Docker 和 CoreOS 容器(当前事实标准);
- Mesos :通用集群资源调度平台,与 marathon 配合提供编排功能。
② 容器管理平台
架在编排引擎之上的更通用平台,通常支持多种编排引擎、屏蔽底层细节,提供应用目录、一键部署等便利功能。
基于 Kubernetes 的平台:
| 平台 | 特点 |
|---|---|
| Rancher(开源免费) | 轻量级 K8s 管理平台,一键部署、管理多集群,兼容云/本地/边缘环境,适合企业统一管控 |
| OpenShift(开源免费) | Red Hat 企业级 K8s 发行版,增加安全、监控、CI/CD 等企业级特性,生态成熟,适合大型企业生产 |
| Kubesphere(开源免费) | 青云开源容器平台,以 K8s 为内核,提供可视化界面降低使用门槛,支持多租户、DevOps 流水线 |
| AWS EKS(商业托管) | 亚马逊云托管 K8s,无缝对接 AWS 生态(存储、负载均衡),稳定性高 |
| Azure AKS(商业托管) | 微软云托管 K8s,集成 Azure 监控、身份认证 |
| 阿里云 ACK(商业托管) | 适配阿里云资源,支持混合云、边缘集群,国内访问快,适合国内企业 |
简化型轻量管理平台:
| 平台 | 特点 |
|---|---|
| Portainer | 超轻量容器管理 UI,支持 Docker 和 K8s,单容器即可部署,界面直观,适合个人测试、小团队 |
| Docker Desktop | Docker 官方桌面工具(Windows/Mac),内置 K8s,个人本地开发首选 |
| Lens | K8s IDE,可视化管集群:资源编辑、日志查看、监控 |
③ 基于容器的 PaaS
为微服务开发提供开发、部署、管理平台,用户不用关心底层基础设施、专注写应用。代表(均为开源):Deis、Flynn、Dokku。
5.3 容器支持技术(周边保障)
| 领域 | 为什么需要 | 代表方案 |
|---|---|---|
| 容器网络 | 容器让网络拓扑更动态复杂,需要专门方案管理容器间、容器与外部的连通性和隔离性 | docker network(Docker 原生);flannel、weave、calico(第三方开源,各有优劣,按需选型) |
| 服务发现 | 微服务动态变化:负载增→自动建容器,负载降→销毁容器;容器还会迁移,IP/端口随时变。client 必须有办法"找到"服务。服务发现保存所有微服务最新的 IP/端口信息,对外提供查询 API | etcd、consul、zookeeper |
| 监控 | 容器的动态特征对监控提出更高挑战 | docker ps/top/stats(原生命令行)+ stats API(HTTP 获取容器状态);sysdig、cAdvisor/Heapster、Weave Scope(开源方案) |
| 数据管理 | 容器常在不同 host 间迁移,持久化数据也要能动态跟着走 | Flocker |
| 日志管理 | 日志是问题排查和事件管理的重要依据 | docker logs(原生);logspout(日志路由:收集各容器日志并转发给其他工具后处理) |
| 安全性 | 容器年轻,安全性一直是业界争论焦点 | OpenSCAP(对容器镜像做扫描,发现潜在漏洞) |
六、Docker 是什么?
6.1 定义【重点】
- Docker 是基于 Go 语言 实现的开源容器项目,2013 年初 诞生,最初发起者是 dotCloud 公司。开源后广受关注,围绕它形成了完整生态;由于影响力太大,dotCloud 干脆改名 Docker Inc,专注 Docker 相关技术。
- Docker 的两大贡献:
- 提供了各种容器管理工具------管理和使用容器变得简单明了;
- 引入分层文件系统构建和高效的镜像机制------迁移难度大幅降低,用户体验极好,操作容器就像操作应用本身。
- 可以把 Docker 容器理解为一种轻量级的沙盒(sandbox) :每个容器里运行一个应用,不同容器相互隔离,也可以通过网络互相通信。创建/停止容器非常快,几乎和创建/终止原生应用一致;资源额外开销远低于虚拟机------很多时候直接把容器当作应用本身也没问题。
6.2 Docker 架构【重点 + 难点】
Docker 采用 C/S(客户端/服务端)架构 ,客户端与 Docker 守护进程通过 Socket 通信:
#mermaid-svg-u3bPQo1pRflbVJXt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-u3bPQo1pRflbVJXt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-u3bPQo1pRflbVJXt .error-icon{fill:#552222;}#mermaid-svg-u3bPQo1pRflbVJXt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-u3bPQo1pRflbVJXt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-u3bPQo1pRflbVJXt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-u3bPQo1pRflbVJXt .marker.cross{stroke:#333333;}#mermaid-svg-u3bPQo1pRflbVJXt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-u3bPQo1pRflbVJXt p{margin:0;}#mermaid-svg-u3bPQo1pRflbVJXt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-u3bPQo1pRflbVJXt .cluster-label text{fill:#333;}#mermaid-svg-u3bPQo1pRflbVJXt .cluster-label span{color:#333;}#mermaid-svg-u3bPQo1pRflbVJXt .cluster-label span p{background-color:transparent;}#mermaid-svg-u3bPQo1pRflbVJXt .label text,#mermaid-svg-u3bPQo1pRflbVJXt span{fill:#333;color:#333;}#mermaid-svg-u3bPQo1pRflbVJXt .node rect,#mermaid-svg-u3bPQo1pRflbVJXt .node circle,#mermaid-svg-u3bPQo1pRflbVJXt .node ellipse,#mermaid-svg-u3bPQo1pRflbVJXt .node polygon,#mermaid-svg-u3bPQo1pRflbVJXt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-u3bPQo1pRflbVJXt .rough-node .label text,#mermaid-svg-u3bPQo1pRflbVJXt .node .label text,#mermaid-svg-u3bPQo1pRflbVJXt .image-shape .label,#mermaid-svg-u3bPQo1pRflbVJXt .icon-shape .label{text-anchor:middle;}#mermaid-svg-u3bPQo1pRflbVJXt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-u3bPQo1pRflbVJXt .rough-node .label,#mermaid-svg-u3bPQo1pRflbVJXt .node .label,#mermaid-svg-u3bPQo1pRflbVJXt .image-shape .label,#mermaid-svg-u3bPQo1pRflbVJXt .icon-shape .label{text-align:center;}#mermaid-svg-u3bPQo1pRflbVJXt .node.clickable{cursor:pointer;}#mermaid-svg-u3bPQo1pRflbVJXt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-u3bPQo1pRflbVJXt .arrowheadPath{fill:#333333;}#mermaid-svg-u3bPQo1pRflbVJXt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-u3bPQo1pRflbVJXt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-u3bPQo1pRflbVJXt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-u3bPQo1pRflbVJXt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-u3bPQo1pRflbVJXt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-u3bPQo1pRflbVJXt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-u3bPQo1pRflbVJXt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-u3bPQo1pRflbVJXt .cluster text{fill:#333;}#mermaid-svg-u3bPQo1pRflbVJXt .cluster span{color:#333;}#mermaid-svg-u3bPQo1pRflbVJXt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-u3bPQo1pRflbVJXt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-u3bPQo1pRflbVJXt rect.text{fill:none;stroke-width:0;}#mermaid-svg-u3bPQo1pRflbVJXt .icon-shape,#mermaid-svg-u3bPQo1pRflbVJXt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-u3bPQo1pRflbVJXt .icon-shape p,#mermaid-svg-u3bPQo1pRflbVJXt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-u3bPQo1pRflbVJXt .icon-shape .label rect,#mermaid-svg-u3bPQo1pRflbVJXt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-u3bPQo1pRflbVJXt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-u3bPQo1pRflbVJXt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-u3bPQo1pRflbVJXt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} docker run 等命令
Socket 通信,只发指令
pull 下载 / push 上传
基于镜像创建实例
用户
Client 客户端
(docker 命令行)
Docker Daemon 守护进程
(宿主机上,真正干活)
Images 镜像
(只读模板)
Containers 容器
(镜像 + 可读写层)
Registry 镜像仓库
Docker Hub 等
三大部分逐一拆解:
① Client 客户端
- 就是我们敲 docker 命令的终端,用户交互入口;
- 关键理解【难点】:客户端不直接做容器创建工作,只是把指令发送给 Docker Daemon(真正干活的在服务端);
- 典型命令:
docker build(构建镜像)、docker pull(拉取镜像)、docker run(基于镜像创建并启动容器)。
② Docker Host 宿主机
宿主机上运行核心组件 Docker daemon(守护进程)------整个架构的服务端,后台常驻进程,真正处理所有 docker 请求:镜像构建、拉取,容器创建、启停、销毁。宿主机内管理两大资源:
Images 镜像【重点】
- 镜像 = 只读的模板(类比:虚拟机镜像 / 类 / 菜谱),是创建容器的基础,包含应用程序、依赖库、配置文件、环境变量。例如"一个基础 OS 环境 + 只装了 Apache"就是一个 Apache 镜像。
- 获取方式:
docker build本地构建,或docker pull从 Registry 下载;甚至可以从网上下载现成的应用镜像直接用。 - 通过版本管理和增量的文件系统,Docker 提供了简单的机制创建和更新镜像。
- 分层存储:镜像由多个只读层叠出来,多个镜像可共享底层(pull 时会看到一层层下载)------节约磁盘。
- 关键限制:镜像只读,不能直接运行,必须基于它实例化成容器。
Containers 容器【重点】
- 容器 = 镜像的运行实例(类比:类 → 实例 / 菜谱 → 炒出来的菜),是一个轻量级沙盒。
docker run时 daemon 读取本地镜像,在只读镜像层之上叠加一层可读写层,生成容器:
#mermaid-svg-xbV3inFUF7vTlc6y{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xbV3inFUF7vTlc6y .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xbV3inFUF7vTlc6y .error-icon{fill:#552222;}#mermaid-svg-xbV3inFUF7vTlc6y .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xbV3inFUF7vTlc6y .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xbV3inFUF7vTlc6y .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xbV3inFUF7vTlc6y .marker.cross{stroke:#333333;}#mermaid-svg-xbV3inFUF7vTlc6y svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xbV3inFUF7vTlc6y p{margin:0;}#mermaid-svg-xbV3inFUF7vTlc6y .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xbV3inFUF7vTlc6y .cluster-label text{fill:#333;}#mermaid-svg-xbV3inFUF7vTlc6y .cluster-label span{color:#333;}#mermaid-svg-xbV3inFUF7vTlc6y .cluster-label span p{background-color:transparent;}#mermaid-svg-xbV3inFUF7vTlc6y .label text,#mermaid-svg-xbV3inFUF7vTlc6y span{fill:#333;color:#333;}#mermaid-svg-xbV3inFUF7vTlc6y .node rect,#mermaid-svg-xbV3inFUF7vTlc6y .node circle,#mermaid-svg-xbV3inFUF7vTlc6y .node ellipse,#mermaid-svg-xbV3inFUF7vTlc6y .node polygon,#mermaid-svg-xbV3inFUF7vTlc6y .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xbV3inFUF7vTlc6y .rough-node .label text,#mermaid-svg-xbV3inFUF7vTlc6y .node .label text,#mermaid-svg-xbV3inFUF7vTlc6y .image-shape .label,#mermaid-svg-xbV3inFUF7vTlc6y .icon-shape .label{text-anchor:middle;}#mermaid-svg-xbV3inFUF7vTlc6y .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xbV3inFUF7vTlc6y .rough-node .label,#mermaid-svg-xbV3inFUF7vTlc6y .node .label,#mermaid-svg-xbV3inFUF7vTlc6y .image-shape .label,#mermaid-svg-xbV3inFUF7vTlc6y .icon-shape .label{text-align:center;}#mermaid-svg-xbV3inFUF7vTlc6y .node.clickable{cursor:pointer;}#mermaid-svg-xbV3inFUF7vTlc6y .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xbV3inFUF7vTlc6y .arrowheadPath{fill:#333333;}#mermaid-svg-xbV3inFUF7vTlc6y .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xbV3inFUF7vTlc6y .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xbV3inFUF7vTlc6y .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xbV3inFUF7vTlc6y .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xbV3inFUF7vTlc6y .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xbV3inFUF7vTlc6y .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xbV3inFUF7vTlc6y .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xbV3inFUF7vTlc6y .cluster text{fill:#333;}#mermaid-svg-xbV3inFUF7vTlc6y .cluster span{color:#333;}#mermaid-svg-xbV3inFUF7vTlc6y div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xbV3inFUF7vTlc6y .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xbV3inFUF7vTlc6y rect.text{fill:none;stroke-width:0;}#mermaid-svg-xbV3inFUF7vTlc6y .icon-shape,#mermaid-svg-xbV3inFUF7vTlc6y .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xbV3inFUF7vTlc6y .icon-shape p,#mermaid-svg-xbV3inFUF7vTlc6y .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xbV3inFUF7vTlc6y .icon-shape .label rect,#mermaid-svg-xbV3inFUF7vTlc6y .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xbV3inFUF7vTlc6y .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xbV3inFUF7vTlc6y .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xbV3inFUF7vTlc6y :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 可读写层(容器新产生的数据写在这里)
镜像层(只读,永不修改)
- 一台宿主机可同时运行多个容器,各自隔离;容器本质 = 宿主机上受 Namespace、Cgroups 管控的进程(对应第三节的两大内核基石)。
- 可以把容器看成"简易版 Linux 环境(root 权限、进程空间、用户空间、网络空间)+ 应用"打包成的盒子,可启动、停止、删除,彼此隔离互不可见。
- 【难点】数据归宿:容器内新产生的数据写可读写层 ,镜像本身不受影响;容器删除后,可读写层数据默认丢失(第三篇会专门讲数据卷来解决这个问题)。
③ Registry 镜像仓库
- 类似代码仓库,集中存放镜像。一个仓库(repository)对应一类镜像,用**标签(tag)**区分版本------例如 Ubuntu 仓库里有 18.04、16.04、14.04、12.04 等版本。
- 按公开与否分:公开仓库(Public) ------最大的是官方 Docker Hub ;国内云商(时速云、阿里云等)提供本地源,国内访问稳定。私有仓库(Private)------本地网络内自建,仅自己访问。
- 工作方式:
docker pull让 daemon 从 Registry 下载镜像到本地;做好镜像后用docker push上传到仓库,下次在其他机器上 pull 下来就能用。
④ 一次 docker run nginx 的完整流程【重点,考试常考】
#mermaid-svg-Jk1rRpp2EXxqPllr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Jk1rRpp2EXxqPllr .error-icon{fill:#552222;}#mermaid-svg-Jk1rRpp2EXxqPllr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Jk1rRpp2EXxqPllr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Jk1rRpp2EXxqPllr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Jk1rRpp2EXxqPllr .marker.cross{stroke:#333333;}#mermaid-svg-Jk1rRpp2EXxqPllr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Jk1rRpp2EXxqPllr p{margin:0;}#mermaid-svg-Jk1rRpp2EXxqPllr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster-label text{fill:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster-label span{color:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster-label span p{background-color:transparent;}#mermaid-svg-Jk1rRpp2EXxqPllr .label text,#mermaid-svg-Jk1rRpp2EXxqPllr span{fill:#333;color:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr .node rect,#mermaid-svg-Jk1rRpp2EXxqPllr .node circle,#mermaid-svg-Jk1rRpp2EXxqPllr .node ellipse,#mermaid-svg-Jk1rRpp2EXxqPllr .node polygon,#mermaid-svg-Jk1rRpp2EXxqPllr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Jk1rRpp2EXxqPllr .rough-node .label text,#mermaid-svg-Jk1rRpp2EXxqPllr .node .label text,#mermaid-svg-Jk1rRpp2EXxqPllr .image-shape .label,#mermaid-svg-Jk1rRpp2EXxqPllr .icon-shape .label{text-anchor:middle;}#mermaid-svg-Jk1rRpp2EXxqPllr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Jk1rRpp2EXxqPllr .rough-node .label,#mermaid-svg-Jk1rRpp2EXxqPllr .node .label,#mermaid-svg-Jk1rRpp2EXxqPllr .image-shape .label,#mermaid-svg-Jk1rRpp2EXxqPllr .icon-shape .label{text-align:center;}#mermaid-svg-Jk1rRpp2EXxqPllr .node.clickable{cursor:pointer;}#mermaid-svg-Jk1rRpp2EXxqPllr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Jk1rRpp2EXxqPllr .arrowheadPath{fill:#333333;}#mermaid-svg-Jk1rRpp2EXxqPllr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Jk1rRpp2EXxqPllr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Jk1rRpp2EXxqPllr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Jk1rRpp2EXxqPllr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Jk1rRpp2EXxqPllr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Jk1rRpp2EXxqPllr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster text{fill:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr .cluster span{color:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Jk1rRpp2EXxqPllr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Jk1rRpp2EXxqPllr rect.text{fill:none;stroke-width:0;}#mermaid-svg-Jk1rRpp2EXxqPllr .icon-shape,#mermaid-svg-Jk1rRpp2EXxqPllr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Jk1rRpp2EXxqPllr .icon-shape p,#mermaid-svg-Jk1rRpp2EXxqPllr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Jk1rRpp2EXxqPllr .icon-shape .label rect,#mermaid-svg-Jk1rRpp2EXxqPllr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Jk1rRpp2EXxqPllr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Jk1rRpp2EXxqPllr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Jk1rRpp2EXxqPllr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 没有
有
- 用户在 Client 执行 docker run nginx
- 请求通过 Socket 发给 Daemon
- 本地有 nginx 镜像吗?
- 访问 Registry 下载镜像,存到本地 Images
- Daemon 读取本地镜像
- 创建容器需要的网络/存储等资源,运行 Container
6.3 Docker 版本演变【了解】
| 阶段 | 时间 | 版本格式 | 关键节点 |
|---|---|---|---|
| 语义化 1.x | 2013--2017.02 | 主.次.补丁(如 1.13.1) | 0.1(2013-06 首发版,基于 LXC);1.0(2014-06 生产可用,Docker Hub 上线);1.12(内置 Swarm 集群,引入 healthcheck);1.13(1.x 最后版本,命令行重构) |
| 日历版本 CE/EE | 2017.03--2022.06 | YY.MM.Patch,分社区版 CE / 企业版 EE |
17.03(首个日历版,runc 落地);17.05(支持多阶段构建);18.09(底层全面使用 containerd);20.10(经典稳定版,支持 cgroup v2、rootless,存量环境大量使用);22.06(日历版终点,Compose-V1 废弃) |
| 回归语义化 23.x+ | 2023.02 至今 | 主.次.补丁 | 23.0(默认启用 BuildKit 构建);24.0/25.0(生产稳定推荐);29.x(最新版,清理大量老旧接口) |
七、动手:安装 Docker 并跑起第一个容器
7.1 实验环境
- 操作系统:CentOS 7(最小化安装)
- 容器 runtime:runc
- 管理工具:Docker Engine
Docker 支持几乎所有 Linux 发行版,也支持 Mac 和 Windows。各系统安装方法见官方文档:https://docs.docker.com/engine/installation/
7.2 环境准备:搭建本地 yum 仓库(复习)
bash
[root@docker ~]# mkdir /dvd
[root@docker ~]# cp /etc/fstab /etc/fstab.bak # 养成好习惯:改配置前先备份
[root@docker ~]# echo '/dev/sr0 /dvd iso9660 defaults 0 0'>> /etc/fstab
[root@docker ~]# mount /dvd
mount: /dev/sr0 写保护,将以只读方式挂载
[root@docker ~]# ls /dvd
CentOS_BuildTag EULA images LiveOS repodata ...
EFI GPL isolinux Packages RPM-GPG-KEY-CentOS-7 ...
# 如果提示"在 /dev/sr0 上找不到媒体":编辑虚拟机设置,关联对应的 iso 文件
# 屏蔽其他源,只保留本地 dvd 源
[root@docker ~]# mkdir /etc/yum.repos.d/bak
[root@docker ~]# mv /etc/yum.repos.d/*repo /etc/yum.repos.d/bak
[root@docker ~]# vim /etc/yum.repos.d/dvd.repo
[dvd]
name=local repo from dvd
baseurl=file:///dvd
gpgcheck=0
# 重建缓存
[root@docker ~]# yum clean all
[root@docker ~]# yum makecache
7.3 防火墙与 Docker 仓库
bash
# 【重点】防火墙不能关闭!部分容器服务需要防火墙的 NAT 功能。
# 把默认 zone 设为 trusted(信任所有),既保留 NAT 能力又不拦截流量
[root@docker ~]# systemctl enable firewalld.service --now
[root@docker ~]# firewall-cmd --set-default-zone=trusted
# 配置 docker-ce 的 yum 仓库(用华为云镜像源)
[root@docker ~]# cat > /etc/yum.repos.d/docker-ce.repo <<'EOF'
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.huaweicloud.com/docker-ce/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=0
EOF
7.4 安装并启动(allinone 部署)
bash
[root@docker ~]# yum install -y docker-ce
# 启动服务并设置开机自启
[root@docker ~]# systemctl enable docker.service --now
7.5 配置镜像加速【重点,国内必做】
目前国内无法直连 docker.io 仓库,必须配置国内镜像加速服务器,否则 pull 会超时失败:
bash
[root@docker ~]# mkdir -p /etc/docker
[root@docker ~]# tee /etc/docker/daemon.json <<'EOF'
{
"insecure-registries": ["hub.hero.cloud"], # 自己搭建的局域网私有仓库
"registry-mirrors": ["http://hub.hero.cloud","https://docker.m.daocloud.io"]
}
EOF
[root@docker ~]# systemctl restart docker
【补充】这两个配置项的区别(初学者容易混):
7.6 验证:跑起前两个容器
bash
# 查看版本,能出版本号说明 daemon 正常
[root@docker ~]# docker --version
Docker version 26.1.3, build b72abbb
# 第一个容器:hello-world(Docker 官方的"安装成功"测试镜像)
[root@docker ~]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
过程拆解(对照 6.2 节架构图理解):① 从 Docker Hub 下载 hello-world 镜像;② 启动 hello-world 容器(输出欢迎信息后容器自动退出------应用跑完了,容器就结束使命了)。
bash
# 第二个容器:httpd(Apache Web 服务器)
[root@docker ~]# docker run -d -p 80:80 httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
852e50cd189d: Pull complete ← 一层一层下载(镜像分层!)
67d51c33d390: Pull complete
......
817f24cca3514568f9b7a7cac6f183734077fb74caf4c62502acd2a4d0d29520 ← 最后输出容器 ID
过程拆解:① 下载 httpd 镜像(里面已装好 Apache HTTP Server);② 启动容器,-p 80:80 把容器的 80 端口映射到宿主机的 80 端口 (第三篇网络管理详讲);-d 让它在后台跑。
验证------宿主机 IP 是 10.1.8.130:
bash
[root@docker ~]# ip -br a
ens33 UP 10.1.8.130/24 ...
docker0 UP 172.17.0.1/16 ... ← Docker 自动创建的网桥,第三篇会讲
[root@docker ~]# curl 10.1.8.130
<html><body><h1>It works!</h1></body></html>
浏览器访问 http://10.1.8.130 看到 "It works!"------两条命令就拥有了一台 Web 服务器,这就是容器的高效。
7.7 C/S 分离部署【难点:亲手验证 Docker 是 C/S 架构】
既然 Client 只发指令、Daemon 才干活,那它们完全可以不在同一台机器上。实验:让 client 机器远程操控 server 机器的 Docker。
server 端(10.1.8.130)------让 daemon 监听 TCP 2375 端口:
bash
[root@docker ~]# dnf install -y docker-ce
# 修改服务配置,让 daemon 额外监听 tcp://0.0.0.0:2375
[root@docker ~]# vim /usr/lib/systemd/system/docker.service
# 在 ExecStart 参数最后添加 -H tcp://0.0.0.0:2375
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl enable docker.service --now
# 验证端口已监听
[root@docker ~]# lsof -i :2375
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dockerd 2565 root 3u IPv6 76021 0t0 TCP *:2375 (LISTEN)
client 端 ------只装命令行工具,用 -H 指定远程 server:
bash
[root@client ~]# dnf install -y docker-ce-cli
# 通过 -H 指定 server 地址执行命令
[root@client ~]# docker -H 10.1.8.130 run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
......
[root@client ~]# docker -H 10.1.8.130 images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 0a30f4c29d25 2 weeks ago 138MB
hello-world latest bf756fb1ae65 11 months ago 13.3kB
结论【考试点】 :client 只做管理,image 和 container 都存储在 server 端------client 机器上并没有装 daemon,也没有镜像。
7.8 Docker 对 Windows 的支持
Docker Engine 可通过 Docker Desktop 在 Windows、macOS、Linux 上使用。Windows 版 Docker Desktop 需运行在 WSL(Windows Subsystem for Linux) 或 Hyper-V 两种架构之上。详见:https://docs.docker.com/desktop/setup/install/windows-install/
八、Docker 镜像管理(第一个核心技能)
镜像 = 只读模板 = 容器的"出生证明"。本节按实际使用顺序:查(search)→ 下(pull)→ 看(ls/inspect/history)→ 改名(tag)→ 删(rm/prune)→ 离线传(save/load)→ 上传(push)。
8.0 先学会查帮助
任何 docker 命令都可以用 --help 或 man 手册查用法:
bash
[root@docker ~]# mandb # 更新 man 数据库
[root@docker ~]# man -k docker # 列出所有 docker 相关手册
docker (1) - Docker image and container command line interface
docker-build (1) - Build an image from a Dockerfile
docker-search (1) - Search the Docker Hub for images
......
[root@docker ~]# man -k docker|grep search # 配合 grep 精确找
[root@docker ~]# man docker-search # 查看详细手册
8.1 search------查找镜像
bash
docker search [OPTIONS] TERM
# -f/--filter 过滤条件;--format 格式化;--limit 结果数量(默认25);--no-trunc 不截断
示例:搜索 3 星以上、带 centos 关键字的镜像:
bash
[root@docker ~]# docker search --filter stars=3 centos
Error response from daemon: ... connection refused
(国内环境直连 docker.io 的搜索接口会失败,属正常现象。)
查询镜像有哪些版本(tag)【重点,实操常需要】
Docker 没有直接列出远程仓库某镜像所有版本的命令,但有三种替代方法:
方法 1:curl 调用 Docker Hub API(推荐,无需装工具)
bash
# 通用格式
curl -s "https://registry.hub.docker.com/v2/repositories/<镜像名>/tags/" | jq '.results[].name'
# 官方镜像(nginx、ubuntu 等)要在名字前加 library/
curl -s "https://registry.hub.docker.com/v2/repositories/library/nginx/tags/" | jq '.results[].name'
# 非官方镜像(如用户 bitnami 发布的 mysql)直接写"用户名/镜像名"
curl -s "https://registry.hub.docker.com/v2/repositories/bitnami/mysql/tags/" | jq '.results[].name'
方法 2:第三方工具 docker-search
bash
pip install docker-search
docker-search tags nginx # 官方镜像
docker-search tags bitnami/mysql # 非官方镜像
方法 3:Docker Hub 网页端(最直观)
打开 https://hub.docker.com/ → 搜索镜像(如 nginx)→ 进入详情页 → 点 Tags 标签,即可查看所有版本(支持过滤和排序)。
查询 Harbor 私有仓库的镜像版本
Harbor 提供 REST API(这就是 7.5 节 insecure-registries 里 hub.laoma.cloud 的身份):
bash
# 查询项目清单
curl -s "http://hub.laoma.cloud/api/v2.0/projects" | jq -r '.[].name'
# 查询项目下有哪些镜像
curl -s "http://hub.laoma.cloud/api/v2.0/projects/library/repositories" | jq -r '.[].name'
# 查询特定镜像的标签
curl -s "http://hub.laoma.cloud/api/v2.0/projects/library/repositories/nginx/artifacts" | jq -r '.[].tags[].name' | sort -V
# 需要认证时用 -u 指定 用户名:密码
curl -s -u student:Student123 "http://hub.laoma.cloud/api/v2.0/projects/library/repositories/nginx/artifacts" | jq -r '.[].tags[].name' | sort -V
8.2 pull------下载镜像【重点】
bash
docker image pull [OPTIONS] NAME[:TAG|@DIGEST]
# -a 下载该仓库所有标签;--platform 指定平台;-q 静默输出
镜像标准命名格式【重点】:
服务器地址:端口/分类/镜像名:tag
例:registry.access.redhat.com/ubi8
例:docker.io/library/centos:8
- 默认使用 Docker Hub,所以"服务器地址"前缀通常省略不写;
- 不写 tag 时默认是
latest。
bash
# 省略前缀,从 Docker Hub(实际走加速器)下载
[root@docker ~]# docker image pull centos:8
latest: Pulling from library/centos
3c72a8ed6814: Pull complete ← 注意!下载是按"层"进行的
Digest: sha256:76d24f3ba3317fa945743bb3746fbaf3a0b752f10b10376960de01da70685fbd
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest
# 写完整服务器地址 → 直接从该镜像服务器下载
[root@docker ~]# docker image pull registry.access.redhat.com/ubi8
观察"分层"【难点】 :3c72a8ed6814 这样的串是层(layer)的唯一 ID(完整 ID 是 256 位、64 个十六进制字符,这里显示的是简写)。
为什么要分层?当不同的镜像包含相同的层时,本地只存一份。例如 centos:8 和某基于 centos:8 构建的镜像,底层完全复用------这就是 Docker 节约磁盘的秘诀,也是"分层文件系统"的含义。
镜像下载后存放在本地:/var/lib/docker/<存储驱动>(本环境是 overlay2)。
8.3 ls------查看本地镜像列表
bash
docker image ls [OPTIONS] [REPOSITORY[:TAG]] # 别名:ls / images / list
# -a 显示全部(含中间层);--digests 显示摘要;-f 过滤;--format 格式化;-q 只显示ID;--no-trunc 不截断
bash
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 958373fdd7e8 4 months ago 148MB
hello-world latest 74cc54e27dc4 4 months ago 10.1kB
centos 8 5d0da3dc9764 3 years ago 231MB
# 用 Go 模板控制输出列
[root@docker ~]# docker image ls --format "{{.Repository}}:{{.Tag}}"
【补充】各列含义:REPOSITORY 仓库名、TAG 版本标签、IMAGE ID 镜像唯一 ID(显示前 12 位)、CREATED 构建时间、SIZE 体积。
一个镜像可以有多个 TAG,但本地只占一份实际空间(见下一节 tag 命令)。
8.4 tag------给镜像打标签
bash
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
# 不改变镜像本身,只是给同一个 IMAGE ID 起了别名
bash
[root@docker ~]# docker image tag centos:8 myos # 起名 myos,tag 省略 = latest
[root@docker ~]# docker image tag centos:8 myos:v1 # 再起一个带版本号的名字
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 8 5d0da3dc9764 3 years ago 231MB
myos latest 5d0da3dc9764 3 years ago 231MB ┐
myos v1 5d0da3dc9764 3 years ago 231MB ┘ 三个"名字",同一个 IMAGE ID、同一份空间
tag 的最佳实践:滚动版本号方案【重点】
Docker 社区通用方案------发布一个版本时同时打 4 个标签。以发布 v1.9.1 为例:
| tag | 指向 |
|---|---|
1.9.1 |
锁定这个具体版本 |
1.9 |
指向 1.9.x 中最新的 |
1 |
指向 1.x 中最新的 |
latest |
指向所有版本中最新的 |
之后发布 v1.9.2:新打 1.9.2,并把 1.9、1、latest 从 v1.9.1 移动到 v1.9.2 ;再发布 v2.0.0:新打 2.0.0、2.0、2,并把 latest 移到 v2.0.0。
#mermaid-svg-TlolOmvZwKCluoWC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TlolOmvZwKCluoWC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TlolOmvZwKCluoWC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TlolOmvZwKCluoWC .error-icon{fill:#552222;}#mermaid-svg-TlolOmvZwKCluoWC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TlolOmvZwKCluoWC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TlolOmvZwKCluoWC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TlolOmvZwKCluoWC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TlolOmvZwKCluoWC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TlolOmvZwKCluoWC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TlolOmvZwKCluoWC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TlolOmvZwKCluoWC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TlolOmvZwKCluoWC .marker.cross{stroke:#333333;}#mermaid-svg-TlolOmvZwKCluoWC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TlolOmvZwKCluoWC p{margin:0;}#mermaid-svg-TlolOmvZwKCluoWC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TlolOmvZwKCluoWC .cluster-label text{fill:#333;}#mermaid-svg-TlolOmvZwKCluoWC .cluster-label span{color:#333;}#mermaid-svg-TlolOmvZwKCluoWC .cluster-label span p{background-color:transparent;}#mermaid-svg-TlolOmvZwKCluoWC .label text,#mermaid-svg-TlolOmvZwKCluoWC span{fill:#333;color:#333;}#mermaid-svg-TlolOmvZwKCluoWC .node rect,#mermaid-svg-TlolOmvZwKCluoWC .node circle,#mermaid-svg-TlolOmvZwKCluoWC .node ellipse,#mermaid-svg-TlolOmvZwKCluoWC .node polygon,#mermaid-svg-TlolOmvZwKCluoWC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TlolOmvZwKCluoWC .rough-node .label text,#mermaid-svg-TlolOmvZwKCluoWC .node .label text,#mermaid-svg-TlolOmvZwKCluoWC .image-shape .label,#mermaid-svg-TlolOmvZwKCluoWC .icon-shape .label{text-anchor:middle;}#mermaid-svg-TlolOmvZwKCluoWC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TlolOmvZwKCluoWC .rough-node .label,#mermaid-svg-TlolOmvZwKCluoWC .node .label,#mermaid-svg-TlolOmvZwKCluoWC .image-shape .label,#mermaid-svg-TlolOmvZwKCluoWC .icon-shape .label{text-align:center;}#mermaid-svg-TlolOmvZwKCluoWC .node.clickable{cursor:pointer;}#mermaid-svg-TlolOmvZwKCluoWC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TlolOmvZwKCluoWC .arrowheadPath{fill:#333333;}#mermaid-svg-TlolOmvZwKCluoWC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TlolOmvZwKCluoWC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TlolOmvZwKCluoWC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TlolOmvZwKCluoWC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TlolOmvZwKCluoWC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TlolOmvZwKCluoWC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TlolOmvZwKCluoWC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TlolOmvZwKCluoWC .cluster text{fill:#333;}#mermaid-svg-TlolOmvZwKCluoWC .cluster span{color:#333;}#mermaid-svg-TlolOmvZwKCluoWC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TlolOmvZwKCluoWC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TlolOmvZwKCluoWC rect.text{fill:none;stroke-width:0;}#mermaid-svg-TlolOmvZwKCluoWC .icon-shape,#mermaid-svg-TlolOmvZwKCluoWC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TlolOmvZwKCluoWC .icon-shape p,#mermaid-svg-TlolOmvZwKCluoWC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TlolOmvZwKCluoWC .icon-shape .label rect,#mermaid-svg-TlolOmvZwKCluoWC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TlolOmvZwKCluoWC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TlolOmvZwKCluoWC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TlolOmvZwKCluoWC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 版本更新
大版本更新
v2.0.0 发布
2.0.0
2.0 / 2 / latest 移到这里
v1.9.2 发布
1.9.2
1.9 / 1 / latest 移到这里
v1.9.1 发布
1.9.1
1.9 / 1 / latest 指向它
用户因此获得灵活性:
myimage:1始终是 1 分支最新版;2.myimage:1.9始终是 1.9.x 最新版;3.myimage:latest始终是最新版;4. 要锁死版本就用myimage:1.9.1。
8.5 inspect------查看镜像详细信息
bash
docker image inspect [OPTIONS] IMAGE [IMAGE...]
# -f/--format:用 Go 模板提取特定字段
docker image inspect myos 输出一个 JSON 数组,重点看这些字段:
| 字段 | 含义 |
|---|---|
Id |
镜像完整 ID(sha256:...) |
RepoTags |
该镜像的所有标签(如 centos:8、myos:latest、myos:v1 都在列) |
RepoDigests |
仓库摘要(从哪个仓库以什么摘要拉来的) |
Created / DockerVersion |
构建时间 / 构建所用 Docker 版本 |
Config |
环境变量 Env、默认命令 Cmd、标签 Labels 等配置 |
Architecture / Os |
架构(amd64)/ 操作系统(linux) |
GraphDriver |
存储驱动(overlay2)及各层目录路径 |
RootFS.Layers |
镜像的分层列表 |
用 -f 提取单个字段(脚本中很常用):
bash
[root@docker ~]# docker image inspect myos -f '{{.Architecture}}'
amd64
[root@docker ~]# docker image inspect myos -f '{{.Os}}'
linux
8.6 history------查看镜像的"分层历史"
bash
docker image history [OPTIONS] IMAGE
# --format 格式化;-H 人类可读(默认);--no-trunc 不截断;-q 只显示 ID
bash
[root@docker ~]# docker image history myos
IMAGE CREATED CREATED BY SIZE COMMENT
5d0da3dc9764 3 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc... 0B
<missing> 3 years ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0... 231MB
# --no-trunc 查看完整命令(上面被截断了)
[root@docker ~]# docker image history myos --no-trunc
每一行 = 构建镜像时执行的一步 = 一层。这个镜像:第 1 层 ADD 进来 231MB 的根文件系统,第 2 层打了 LABEL(0B,只是元数据),第 3 层设置了默认 CMD(0B)。history 是理解"镜像分层"最直观的工具。
8.7 rm------删除镜像【重点 + 易错】
bash
docker image rm [OPTIONS] IMAGE [IMAGE...] # 别名:rm / rmi / remove
# -f 强制删除;--no-prune 不删除未打标签的父层
核心规则【考试点】:一个镜像有多个标签时,rm 一次只删一个标签;删到最后一个标签才真正删除镜像。
bash
# myos 有 latest 和 v1 两个标签 → 只删掉一个标签,镜像还在
[root@docker ~]# docker image rm myos
Untagged: myos:latest
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID SIZE
myos v1 5d0da3dc9764 231MB ← 还在
centos 8 5d0da3dc9764 231MB
# 删除最后一个标签 → 镜像本体和它的所有层被删除
[root@docker ~]# docker image rm myos:v1
Untagged: myos:v1
[root@docker ~]# docker image rm centos:8
Untagged: centos:8
Untagged: centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Deleted: sha256:5d0da3dc9764... ← 注意 Deleted 了多个层
Deleted: sha256:74ddd0ec08fa...
按 ID 删除(会自动删掉该镜像的所有标签和所有层):
bash
[root@docker ~]# docker image rm 958373fdd7e8 # 删除 httpd
Untagged: httpd:latest
Deleted: sha256:958373fdd7e8...(多个层依次删除)
8.8 prune------批量清理镜像
bash
docker image prune [OPTIONS]
# -a 删除所有"没有被容器使用"的镜像(不加 -a 只删悬空镜像 dangling);--filter 过滤(如 until=时间);-f 免确认
bash
[root@docker ~]# docker pull nginx
[root@docker ~]# docker image prune -a <<< "y"
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] Deleted Images:
untagged: nginx:latest
......
Total reclaimed space: 117.7MB
思考:为什么 httpd 和 hello-world 没有被删掉?
因为这两个镜像正被容器使用着(哪怕是已退出的容器也算):
bash
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
be05a7c31635 httpd "httpd-foreground" Up About a minute 80->80 gifted_williams
4974ee579b36 hello-world "/hello" Exited (0) 4 minutes ago keen_kare
【难点】这是 Docker 的保护机制:容器(即使已退出)会"引用"它基于的镜像,被引用的镜像不许删。想彻底删除,必须先删掉(或强制删除)相关容器。
8.9 save / load------镜像的离线导出与导入【重点】
Docker 默认用 overlay2 存储驱动(docker info | grep 'Storage Driver' 可查看),镜像实际存储在 /var/lib/docker/overlay2 的分层目录里,直接拷贝这些文件非常复杂。正确姿势是用 save/load:
bash
# save:把本地镜像打包成 tar 文件(可一次打包多个镜像)
docker image save [OPTIONS] IMAGE [IMAGE...] # -o 输出到文件
[root@docker ~]# docker save httpd -o httpd.tar
[root@docker ~]# docker save httpd hello-world -o images.tar
[root@docker ~]# ls *tar
httpd.tar images.tar
# load:从 tar 文件导入镜像
docker image load [OPTIONS] # -i 指定输入文件;-q 静默
[root@docker ~]# docker image load -i images.tar
Loaded image: httpd:latest
Loaded image: hello-world:latest
配合"被容器引用就删不掉"的知识,看一个删除实验:
bash
# 直接删正在被使用的镜像 → 报错
[root@docker ~]# docker image rm httpd hello-world
Error response from daemon: conflict: unable to remove repository reference "httpd" (must force) - container be05a7c31635 is using its referenced image 958373fdd7e8
# 加 -f 强制删除 → 标签删掉了,但镜像显示为 <none>(仍被容器占用着)
[root@docker ~]# docker image rm httpd hello-world:latest -f
Untagged: httpd:latest
......
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID SIZE
<none> <none> 958373fdd7e8 148MB ← 镜像本体还在
# 结论:要真正释放空间,需删除容器后再删镜像
8.10 push------把本地镜像推送到仓库
本地镜像默认推送到 docker.io,推送前必须先登录:
bash
docker login [OPTIONS] [SERVER]
# -u 用户名;-p 密码;--password-stdin 从标准输入读密码(更安全)
[root@docker ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. ...
Username: mage16196
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json. ← 提示:密码明文存在本地
Login Succeeded
(注:docker.io 国内目前无法访问,实际登录会超时失败。)
推送格式要求【考试点】:镜像名必须符合 username/image:tag------Docker 靠镜像名前缀判断该推到哪个账户下,所以要先 tag 再 push:
bash
# 第一步:把镜像 tag 成 "自己用户名/镜像名" 的格式
[root@docker ~]# docker image tag hello-world:latest mage16196/myhello
# 第二步:推送
[root@docker ~]# docker image push mage16196/myhello
The push refers to repository [docker.io/mage16196/myhello]
9c27e219663c: Layer already exists ← 底层和官方 hello-world 相同,直接复用(分层的好处又体现了一次)
latest: digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 size: 525
推送成功后可登录 Docker Hub 网页端管理已上传的镜像。
本篇知识自测清单
看完本篇,你应该能不假思索地回答:
- 容器解决了什么问题?(N×M 矩阵 / 环境不一致,集装箱类比)
- 容器和虚拟机的本质区别?(共享内核 vs 各带内核,对比表 7 项)
- 容器靠哪两大内核技术实现?分别负责什么?(Namespace 隔离 / Cgroups 限制)
- Docker 架构三大部分?谁真正干活?(Client / Host(daemon+镜像+容器) / Registry;daemon 干活)
- 镜像和容器的关系?(只读模板 vs 运行实例 + 可读写层)
- 镜像为什么分层?好处?(不同镜像共享相同层,省磁盘)
- 删除多标签镜像的规则?(删标签,直到最后一个才删本体)
- 为什么有的镜像删不掉?(被容器引用)
- save 和 pull/push 的适用场景?(离线分发 vs 在线仓库)
- 三条必会命令:
docker run hello-world、docker image pull、docker image ls。