先建立模型
镜像提供起点,容器各自保存变化
镜像(Image)是运行程序所需文件与配置的只读包。它本身不会运行。容器(Container)是从镜像创建的运行实例,包含隔离的进程环境和自己的文件变化;程序退出后,容器也可以处于停止状态。
仓库(Registry,镜像仓库服务)保存并分发镜像。你先把镜像拉到本地,再从本地镜像创建容器。容器运行期间,通常无需持续连接仓库。
从同一镜像创建 A、B。A 在自己的文件系统里写了 /note(未使用共享存储)。B 会自动看到这个文件吗?镜像会改变吗?先写下理由。
都不会。每个容器有自己的可写层,也就是记录本容器文件变化的地方。A 的变化只属于 A,既不回写镜像,也不自动传给 B。
如果你懂“类和实例”,这个类比能用到哪里?
“一个类能创建多个实例”能帮助理解镜像的一对多关系。但容器还包含进程环境和自己的可写层。删除实例后再创建一个,旧容器的文件变化不会自动回来。镜像本身由多层组成,分层机制留到模块 2。
你只执行了一次 docker pull nginx:1.27。现在能推出什么?
pull 负责下载;创建并启动新容器是 run 的工作。
拉取是获取本地副本,不是从远端搬走镜像。
pull 的终点是本地镜像。要运行程序,还需要从镜像创建容器;远端镜像仍可供别人拉取。
读懂你要拉什么
镜像引用写出位置、名字和标签
镜像引用是命令里用来指定镜像的名字。把 docker.io/library/nginx:1.27 按斜杠和冒号拆开:
docker.io /仓库地址 · Registrylibrary /命名空间 · Namespacenginx :名字 · Repository1.27标签 · Tag命名空间(Namespace)通常是用户或组织名;Docker Hub 的 library 用于官方镜像。镜像集合(Repository)把相关镜像归在一个名字下,如 library/nginx。一个 Registry 可管理很多这样的集合。
标签(Tag)是指向镜像的可变名字。这里的 1.27 用于拆解引用,不表示推荐部署这个版本。latest 也只是一个标签,不保证版本号最大。
| 你写的引用 | 补全后的含义 | 补上什么 |
|---|---|---|
nginx:1.27 | docker.io/library/nginx:1.27 | 地址、官方命名空间 |
nginx | docker.io/library/nginx:latest | 再补标签 latest |
team/web | docker.io/team/web:latest | 已有 team,不再补 library |
其他仓库地址有端口时怎么读?
registry.example.com:5000/team/web:v1 中,:5000 是仓库服务端口,最后的 :v1 才是标签。library 是 Docker Hub 官方镜像的约定,不是任意私有仓库都会提供的目录。更严格的不可变引用使用摘要(digest,内容标识),留到镜像标签与版本管理一页。
命令里只写 alpine。请补全四段,不运行命令也能回答。
地址 / 命名空间 / 名字 : 标签
完整引用是 docker.io/library/alpine:latest。省略字段会采用默认值,名字 alpine 本身必须给出。
把动作放回图上
四条命令连对象,两条命令删本地对象
run 每次创建并启动一个新容器。默认情况下,本地缺少所需镜像时,它会先拉取;本地已有时通常直接使用,并不总会检查远端更新。
- pull:把仓库里的镜像下载到本地,远端保留。
- run:从本地镜像创建并启动新容器。先猜:保存容器里的文件变化,箭头应往哪里走?
- commit:从容器的变化创建新镜像,原镜像不被改写。
- push:把本地镜像上传到有写入权限的仓库目标。
- rm:删除指定容器,不删除源镜像。先猜:清理本地镜像要用什么命令?会删除远端吗?
- rmi:处理本地镜像或标签,不删除远端。图中箭头汇总六个动作,并非要求依次执行的脚本。
commit 把容器的文件变化与配置保存为新镜像。原镜像和原容器都保留。push 上传镜像,不上传活着的进程;实际推送还需要目标名字以及仓库写入权限。
commit 会保存“运行现场”吗?
它不保存进程内存,也不包含挂载数据卷里的数据。数据卷是独立于容器可写层的数据存储,模块 4 会展开。可重复构建通常用 Dockerfile(描述构建步骤的文本文件);这里学习 commit 只是为了理解方向。
先选命令,再选正确的箭头。可点击,也可用 Tab 和 Enter 完成。
- docker pull
- docker run
- docker commit
- docker push
pull / push 负责本地与远端的镜像传递;run 创建容器,commit 创建新镜像。四条命令都不删除源对象。rm / rmi 的删除目标在后面再练。
动手 · 约 4 分钟
两次 run 验证:文件变化属于容器
实测于 2026-11-04,Docker Engine 29.1.3,由维护者提供;Linux 内核 7.3.0-1004-oem,x86_64。复现前需要 Docker 已启动,当前用户可执行 Docker。
在宿主机终端按顺序执行。实验会下载镜像、占用本地磁盘,并创建临时容器;使用 --network none 禁用实验容器联网,不映射端口、不挂载宿主机目录。拉取镜像仍需宿主机能访问 Docker Hub。
alpine:3.21 是本实验使用的 Linux 镜像引用。镜像中的 sh -c 用来执行引号内的 Linux 命令。--rm 表示程序退出后自动删除这个容器,保留镜像。
1. 创建 A:缺少镜像时自动拉取,再写入文件
实测前没有 alpine:3.21。直接运行第一条命令,Docker 先拉取镜像,随后在 A 内写入并读取文件。
从 Unable to find image、Pulling from、Pull complete 到 Digest、Status: Downloaded newer image,这些才是本次拉取的日志。最后的 only-A 来自容器内的 cat;随后 A 退出并由 --rm 自动删除。
2. 创建 B:检查相同路径
B 打印 absent,说明它没有 A 写入的文件。B 退出后也自动删除。
3. 两个容器删除后,镜像仍在
IMAGE 列的 alpine:3.21 把名称和标签放在一起;ID 是镜像标识。DISK USAGE 与 CONTENT SIZE 分别显示磁盘占用与镜像内容大小;没有单独的 SIZE 列。EXTRA 本次为空;若出现 U,表示镜像正被容器使用,停止的容器也算引用。
摘要、ID、大小和拉取进度均保留自原始记录,你的机器会不同。应关注 only-A → absent,以及容器删除后镜像仍然存在。若拉取失败,先检查网络、权限或服务是否启动。
Docker 29 的镜像列表为什么和旧教程不同?
Docker 29 默认改用新视图,表头为 IMAGE / ID / DISK USAGE / CONTENT SIZE / EXTRA。前面的 WARNING 是可读性提示,并非拉取失败;脚本读取请用 --format。旧版本示例把 REPOSITORY、TAG、SIZE 分列展示。参见 Docker 29 发布说明与 docker image ls 文档。
B 为什么打印 absent?请同时解释“镜像仍在”和“A 写过的文件不在”这两件事。
A 的文件写在 A 的可写层里,镜像没改变。A 退出时 --rm 删除 A 和它的可写层。B 由原镜像重新创建,所以没有 A 的文件。删除容器不会删除镜像。
- 提到 A 的可写层独立于镜像
- 提到 --rm 自动删除退出的容器
- 提到 B 从原镜像创建,而不是接着 A 的文件运行
可选清理:不再需要这个实验镜像时
只在确认其他工作不依赖这个本地引用时执行 docker rmi alpine:3.21。它只处理本地镜像或标签,远端镜像还在。若提示容器引用等冲突,先保留它,不要为实验加 -f 强删。
删除的边界
删除要看目标,也要看是否有引用
docker rm 容器名 删除容器及其可写层。普通 rm 通常要求容器已停止;停止只是进程退出,容器对象和文件变化仍然保留。docker rmi 镜像引用 删除本地镜像或取消标签,不删除远端。
B 仍在,A 自己的文件变化丢失。可以从原镜像再创建 C。
按镜像 ID 尝试普通 rmi,可能因引用被拒绝;停止的容器也可能阻止删除。命令失败不等于 A 被删除。
成功 rmi 后本地没有这个镜像。以后还能 pull;没有容器被顺带删除。
只看命令的目标,不实际执行。把四个删除动作分到对应对象。
- docker rm A
- docker rmi alpine:3.21
- docker rm B
- docker rmi nginx:1.27
rm 的目标是容器;rmi 的目标是本地镜像或标签。分类表示命令意图,执行能否成功还要检查停止状态和引用冲突。
为什么 rmi 成功也不一定释放全部空间?
一个镜像可以有多个标签。删除某个标签可能只是取消这个名字;其他标签或容器仍可引用相同内容。不要把“名字消失”理解成“所有底层数据立即消失”。这里不使用强制删除;具体空间回收和存储后端留到后续模块。
A 已停止但还没删除。你执行 rmi 后收到引用冲突。此时 A 的文件变化、本地镜像、远端镜像分别还在吗?
这个场景中三者都还在。A 停止不等于删除,文件变化仍留在可写层;rmi 被拒绝,本地镜像未删;远端也不受本地删除影响。若确实不再需要 A 的文件,应先删除 A,再处理镜像引用。
只删除停止的 A,B 由同一镜像创建且仍在运行。镜像原本来自 Docker Hub。成功 rm A 后哪组状态正确?
rm 的目标是容器,删除镜像要另做 rmi。
共享起点不等于共享生命周期。B 是另一个独立容器。
rm A 只移除 A 及其可写层。B 的运行和可写层不受影响,本地镜像保留,仓库中供分发的镜像也保留。
合上页面前
用四句话还原整张图
- 仓库分发镜像;镜像是只读起点;每个容器有自己的运行环境和可写层。
nginx补全为docker.io/library/nginx:latest;latest 是默认标签名。- pull / push 连远端与本地镜像;run / commit 连镜像与容器,分别创建新对象。
- rm 删容器;rmi 处理本地镜像或标签,可能因引用被拒绝;两者都不删除远端副本。
同事说:“把正在跑的容器 push 给我,我启动后就能看到你刚写的文件。”你会怎样用三种对象解释正确做法?
push 的对象是镜像。若文件只在容器可写层里,直接 push 原镜像不会带上它。可以先用 commit 把容器变化保存为新镜像,再用有权限的目标名字 push。同事 pull 新镜像并 run 后才得到包含那些文件的新容器,进程内存不会被转移。
- 区分镜像分发与容器运行
- 指出 commit 产生新镜像,push 上传镜像
- 指出新容器不等于原进程的运行现场
来源与核对范围
截至 2026-11-03,Docker Engine 29.x。以下为核对概念和 CLI 行为的官方文档;示意图不表示磁盘上的具体存储布局。实验引用维护者在 Issue #10 提供的 2026-11-04 记录(Docker Engine 29.1.3,Linux 7.3.0-1004-oem,x86_64)。
- What is an image?:镜像只读、不可变与分层概念。
- What is a registry?:Registry 与 repository 的区别。
- docker image tag:引用格式、docker.io / library / latest 默认值。
- docker container run、Running containers:创建运行、默认拉取策略、--rm 与 none 网络。
- docker image pull、docker image push:下载、上传与仓库凭据。
- docker container commit:生成新镜像,不保存挂载卷数据。
- docker container rm、docker image rm:删除目标、标签与引用限制。Explore the Images view 同时说明运行或停止的容器对删除镜像的限制。
- Storage:每个容器独立的可写层及其删除边界。
- docker image ls 与 Docker Engine 29.0 发布说明:镜像列表、格式化输出与默认视图变更。