逆向解析Docker镜像文件
了解 Docker 镜像的分层存储原理和对应机制!
我们在学习了 Docker 相关的知识和使用之后,肯定很好奇 Docker 镜像中文件到底是怎么分的呢?它又是怎么存储起来的呢?我们怎么在不启动镜像的情况找到镜像中的对应文件呢?咳咳咳,那我们就带着这些问题,一起来看看吧!

1. 探究问题起因
想要了解一个东西肯定是因为某些原理作为出发点的!
我们设想一下,我们最近刚刚面试完,进入了一个新的公司。在刚入职的第一天,直属上司分配给我们一个简单的任务,就是:编写某应用程序对应镜像的 Dockerfile 文件! 我们的公司(A)之前让另一家公司(B)开发了一个 Web 应用程序,而公司(B)后来该项目的托管和维护交给了外包公司(C)来负责。外包公司(C)将其分配给了(C1)来负责,而其定制化了一个 Docker 镜像并创建了对应的 Dockerfile 文件,但是并没有提交上去。 恰好在你入职的时候,C1 这个人早已不在职了,现在公司继续更新一版对应服务,所以该任务就到了你的手里了。咳咳咳,开始你的表演吧! 幸运的是,Docker 镜像格式的透明度要高得多,所以我们只需要进行一些简单的“侦查”工作,就可以大致分析出来镜像文件的构成方式,并可以得出很多有趣的结论。 我们知道 Docker 镜像是分成一层一层的,堆叠在一起组成的。而 Dockerfile 文件中几乎每条指令都会变成了一个描述该指令对应变化的层。比如,如果你的 Dockerfile 文件中有这样一条 RUN script.sh 指令的话,它用于创建一个真正的大文件,然后你用 RUN rm really big 文件删除它,实际上在 Docker 镜像中得到是两个层。
2. 镜像存储方式
任务:编写某应用程序对应镜像的 Dockerfile 文件!
- 首先,在我们本地拉去对应的镜像,并将其导出到一个文件中去。
# 拉取镜像 [email protected]:~/test$ sudo docker pull tmknom/prettier:2.0.5 2.0.5: Pulling from tmknom/prettier cbdbe7a5bc2a: Pull complete a0ab3bb12e81: Pull complete e2ff8799a99a: Pull complete Digest: sha256:85a60938fa30459683c7dd2bec2e80998d57227bf2c6da7bb541458d080b28fc Status: Downloaded newer image for tmknom/prettier:2.0.5 docker.io/tmknom/prettier:2.0.5 1. 导出镜像 [email protected]:~/test$ docker save tmknom/prettier:2.0.5 > prettier.tar
- 导出镜像之后,我们再分析其文件目录结构,可以看到其是以 tar 文件进行归档的。
# 解压镜像 [email protected]:~/test$ tar -xf prettier.tar 1. 目录结构 [email protected]:~/test$ tree . . ├── repositories ├── manifest.json ├── 88f38be28f05f38dba94ce0c1328ebe2b963b65848ab96594f8172a9c3b0f25b.json ├── a9cc4ace48cd792ef888ade20810f82f6c24aaf2436f30337a2a712cd054dc97 │ ├── json │ ├── layer.tar │ └── VERSION ├── d4f612de5397f1fc91272cfbad245b89eac8fa4ad9f0fc10a40ffbb54a356cb4 │ ├── json │ ├── layer.tar │ └── VERSION └── 6c37da2ee7de579a0bf5495df32ba3e7807b0a42e2a02779206d165f55f1ba70 ├── json ├── layer.tar └── VERSION
- manifest.json
- Config -> 对应镜像相关信息的主配置文件
- RepoTags -> 对应镜像的名称和对应版本号
- Layers -> 对应镜像包的分层目录列表信息