首页  /  云原生  /  正文

Docker 镜像原理与常用命令

云原生 2026-10-02📖 15 分钟👁 —
🐳 云原生 · Docker第 2 / 9 页123456789📖 完整导航 →

一、命令忘了怎么查

三个保底的命令,先记住:

docker version
docker info # 显示一些运行信息
docker 命令 --help

之后哪个命令不会用,就去官方文档查,命令和参数都在里面,把 Reference 展开就是 CLI reference:

docker 文档站 Reference 下面的 CLI reference,命令都在这儿查

https://docs.docker.com/reference

https://docs.docker.com/


二、镜像相关的命令总览

先把和镜像有关的命令列出来,后面逐个上手:

命令说明
docker image build从 Dockerfile 构建镜像
docker image history查看镜像的构建历史
docker image import从 tar 包导入文件系统创建镜像
docker image inspect查看镜像详细信息
docker image load从 tar 归档或标准输入加载镜像
docker image ls(也就是 docker images)列出所有镜像
docker image prune删除未使用的镜像
docker image pull从仓库下载镜像
docker image push上传镜像到仓库
docker image rm删除一个或多个镜像
docker image save将镜像保存到 tar 归档文件
docker image tag给目标镜像打标签

三、看本地有哪些镜像

root@VM-0-9-ubuntu:~# docker images
                                                                                                      i Info →   U  In Use
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   c3cbe1cc1aa5       25.9kB         9.49kB    U   

# 解释
IMAGE    镜像仓库源
ID        镜像ID
DISK USAGE  磁盘占用
CONTENT SIZE  内容大小
EXTRA       状态U,正在使用

它支持的选项:

选项说明
-a, --all显示所有镜像(默认隐藏中间层和悬空镜像)
--digests显示摘要信息
-f, --filter按条件过滤输出
--format使用自定义模板格式化输出
--no-trunc不截断输出
-q, --quiet只显示镜像 ID
--tree实验性功能,以树形结构列出多平台镜像

--format 支持这几种写法:

平时最常用的就是 -q 和 -a,配合起来只拿 ID:

root@VM-0-9-ubuntu:~# docker images -aq
c3cbe1cc1aa5

四、搜索镜像

docker 镜像都放在 docker hub,相当于一个镜像商店,可以在官网搜,也可以在 linux 里搜。

docker search 镜像名

(我这边网络问题没法演示,先把参数记下来。)

选项说明
-f, --filter按条件过滤搜索结果
--format使用 Go 模板美化输出格式
--limit限制最大搜索结果数量
--no-trunc不截断输出内容

可以用 -f 过滤出收藏多的,比如大于 3000 的:

docker search -f stars=3000 mysql

五、拉取镜像

docker pull 是唯一会走镜像加速的命令,其他命令不加速,这点记一下。

root@VM-0-9-ubuntu:~# docker pull --help
Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Download an image from a registry

Aliases:
  docker image pull, docker pull

Options:
  -a, --all-tags          Download all tagged images in the repository
      --platform string   Set platform if server is multi-platform capable
  -q, --quiet             Suppress verbose output
选项全称作用
-a--all-tags下载仓库里所有带标签的镜像(不常用,会下很多)
--platform—指定平台架构(如 linux/amd64、linux/arm64)
-q--quiet安静模式,减少输出信息

拉的时候能看到下载信息,一层一层往下走:

root@VM-0-9-ubuntu:~# docker pull mysql
Using default tag: latest # 不写tag默认最新,版本必须是仓库存在的
latest: Pulling from library/mysql
71fecf9a0313: Pull complete # 分层下载,镜像核心,联合文件系统
35c80c3f0cad: Pull complete 
30627cea5424: Pull complete 
718475825f6a: Pull complete 
0fab344c2070: Pull complete 
7ee3c7ac3aeb: Pull complete 
7a08e28acd68: Pull complete 
1fc0feac79ef: Pull complete 
234be8523cd7: Pull complete 
3bfe3c84c770: Pull complete 
58ddc8cbf912: Download complete 
ebf48244f5b5: Download complete 
# 签名
Digest: sha256:cbade841779f1661300e705721f9d2ff159865cc7a8a291affbff43ac6ec7f1d
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
# docker pull mysql 等价于 docker pull docker.io/library/mysql:latest

root@VM-0-9-ubuntu:~# docker pull mysql:5.7
5.7: Pulling from library/mysql
df9a4d85569b: Pull complete 
20e4dcae4c69: Pull complete 
1c56c3d4ce74: Pull complete 
e9f03a1c24ce: Pull complete 
68c3898c2015: Pull complete 
6b95a940e7b6: Pull complete 
90986bb8de6e: Pull complete 
ae71319cb779: Pull complete 
ffc89e9dfd88: Pull complete 
43d05e938198: Pull complete 
064b2d298fba: Pull complete 
96889c47a44a: Download complete 
9eb6a52b8441: Download complete 
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7


root@VM-0-9-ubuntu:~# docker images
                                                                                                      i Info →   U  In Use
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   c3cbe1cc1aa5       25.9kB         9.49kB    U   
mysql:5.7            4bc6bc963e6d        700MB          149MB        
mysql:latest         cbade841779f       1.28GB          288MB   

关于镜像分层缓存:docker pull mysql:latest 拉下来的其实是 MySQL 8.0,docker pull mysql:5.7 是 5.7 版本。虽然都叫 MySQL,但底层基础层(比如 71fecf9a0313 和 df9a4d85569b)来自不同的构建,镜像 ID 也不一样,所以 Docker 不会把它们当成"已存在"的层,缓存共用不上。

拉 mysql:5.7 时前面几层直接显示 Already exists,复用了本地的镜像缓存

这张图里红框标出来的 Already exists 就是不需要重复下载、可以直接共用的缓存层。


六、镜像为什么是一层层的

前面 pull 的时候看到的 Pull complete、Already exists,还有"两个 mysql 版本共用不上缓存"这件事,根子都在分层上。

镜像不是一个整块的文件,而是一层一层叠出来的。FROM debian 是第一层,再来一句 RUN apt-get install emacs 就多一层,再 RUN apt-get install apache2 又一层 —— 每一层都盖在内核和已有的镜像之上:

FROM debian、装 emacs、装 apache2,每条指令都在内核和已有镜像之上再叠一层

整个镜像最底下那层是 bootfs:

bootfs(boot file system)里有 bootloader 和 kernel,它在镜像的最底层,引导完就卸载

bootfs 和典型的 Linux/Unix 系统一样,装的是 bootloader 和 kernel;boot 加载完成、内核进了内存之后,bootfs 就卸载了。它上面才是 rootfs:

rootfs 在 bootfs 之上,装的是 /dev、/proc、/bin、/etc 这些标准目录,也就是各种发行版本身

rootfs 就是 Ubuntu、CentOS 这些发行版的文件系统。容器其实就是一个小号的虚拟机环境,只不过它和宿主机共用同一个内核。

再往上就是一层层的镜像层了。拿一个常见的例子:第 1 层是 Ubuntu 16.04,第 2 层装 Python,第 3 层打安全补丁 —— 这三层合起来才是那个"镜像",单独拿出任何一层都不是:

第 1 层 Ubuntu 16.04、第 2 层 Python、第 3 层 Security Patch,合起来才是一个完整镜像

层与层之间是叠加,不是替换。第 1 层里有文件 1、2、3,第 2 层里有文件 4、5、6,那么这个镜像里就是 6 个文件:

每层各放 3 个文件,镜像里能看到两层加起来的 6 个文件

这也解释了不同的镜像为什么能共用底下的层。app1.0 在 centos、mysql 这些底层之上加了自己的文件,app2.0 只是在 app1.0 的基础上又多了一个文件 7,下面的层是共用的,所以 2.0 只多占一个文件的空间:

app1.0 和 app2.0 共用 centos、mysql 这些底层,app2.0 只多了一个文件 7

最后是镜像和容器的关系:镜像的每一层都是只读的,容器跑起来的时候 docker 会在最上面再盖一个可写的容器层,你在容器里做的所有操作都写在这一层:

容器在只读镜像之上加一层可写层,所有改动都写在这里,下面 tomcat 那层动不了

所以 docker commit 能把容器那层的改动提交成一个新镜像;而容器一删,这层可写层也跟着没了 —— 这也是后面要讲数据卷的原因。


七、删除镜像

docker rmi -f 镜像ID # 该镜像全删
root@VM-0-9-ubuntu:~# docker rmi -f 4bc6bc963e6d
Untagged: mysql:5.7
Deleted: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
root@VM-0-9-ubuntu:~# docker images
                                                                                                      i Info →   U  In Use
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   c3cbe1cc1aa5       25.9kB         9.49kB    U   
mysql:latest         cbade841779f       1.28GB          288MB 

# 批量删除全部的,传入所有镜像的id,这里习惯上用了反引号
# $() 是命令替换,它会执行括号里的命令,然后把输出结果作为外层命令的参数
docker rmi -f $(docker images -aq)
root@VM-0-9-ubuntu:~# docker rmi -f `docker images -aq`
Untagged: mysql:latest
Deleted: sha256:cbade841779f1661300e705721f9d2ff159865cc7a8a291affbff43ac6ec7f1d
Untagged: hello-world:latest
Deleted: sha256:c3cbe1cc1aa588a64951ac6286e0df7b27fe2e6324b1001c619bb358770c0178
root@VM-0-9-ubuntu:~# docker images
                                                                                                      i Info →   U  In Use
IMAGE   ID             DISK USAGE   CONTENT SIZE   EXTRA
root@VM-0-9-ubuntu:~# 

$(...) 和反引号是一个意思,都是命令替换,实际敲的时候用 $(...) 更清楚,反引号容易看错。


八、镜像的导出、导入和 commit

这几个命令基础部分没细讲,先把名字和用途对上,后面 Dockerfile 那几页会展开:

镜像的东西就这些,容器怎么跑起来在下一页。