如何反编译一个Docker镜像还原Dockerfile?

前言

现在对于一个开发来说,Docker应该是再熟悉不过了。还记得在20132014左右的时候,听说多最多的就是Cloud Foundry,那个时候就一直在说云的事情。后面Docker就绝杀了它

那它帮我们解决了一个什么问题了?面试的时候也许会问到。

在很久以前,我们开发代码,估计最蛋疼的事情就是发布版本了。我还记得在房多多的时候(2014~2016)左右,每次发布几个开发围绕在运维的身边,有时候运维忙不过来,开发就直接在运维的电脑上开始VIM干活了,修改若干配置。由于多环境的原因,我们无法保证每个环境都是一样的。

  • 可能你的操作系统不同,导致打包、发布的脚本不同
  • 环境不同,没有很好的配置管理,你的代码有不同的写法
  • 特别是跟操作系统相关的那些参数,可能瞬间就会带来性能问题

那么Docker就可以把我们的操作系统、代码、脚本等都一起打包成一个Image,就可以保证只要是运行同一个Image,我们的所有内容都是一样的。就不会出现,我在测试环境跑的好好的,一到生产连启动都成问题。

问题

现在一般一个POD就只跑一个进程,DevOps会根据我们的发布流水线自动的将一个项目进行打包、发布,整套的CI、CD做的是行云流水。但是,每个项目ROOT下都会需要一个叫Dockerfile的文件。但偏偏有一些历史项目,没有Dockerfile文件,只有一个Run的容器再跑,真的是非常惊悚。docker rm [OPTIONS] CONTAINER [CONTAINER...],就GAME OVER了。

怎么办?

方法1:以当前容器作为基础镜像

真的,什么也不想。先保个底,把你当前的容器打包成一个镜像推送到仓库里去,哪天有以外或者说需要基于它做一些事情的时候才有可能。比如:你要本地也部署一份代码来debug

一般都是私有的仓库,会需要输入用户名与密码

1
2
3
4
➜  ~ docker login {仓库地址}
Username: chenyuan
Password:
Login Succeeded

然后,将镜像打包推送到私有仓库去

1
2
3
4
5
docker commit -a "name" -m "小陈来拯救你" 706e502e8693 {镜像地址}:{tag}

docker push {镜像地址}:{tag}

docker pull {镜像地址}:{tag}

但是这样子的问题在于,我们无法知道环境依赖了哪些模块,如果需要重新再部署一套,我为了保证环境的干净又需要删除哪些东西。就是无法知道增加与减少哪些东西,也就会导致环境存在不一致性,失去了我们的初衷。

方法2:从运行的容器中复制

先把镜像跑起来,然后从运行起来的容器中复制文件出来,复制命令如下:

1
2
3
# 从容器复制文件或目录到宿主机器
docker cp 6619ff360cce:/opt/h2-data/pkslow ./
docker cp 6619ff360cce:/opt/h2-data/pkslow/pkslow.txt ./

第一种方法并不是万能的,因为有些镜像过于简单,少了许多基础命令,以至于无法复制文件,也无法进入shell环境。其次,要运行起来再操作,也有点占用资源,比较麻烦。

方法3:解压镜像tar文件(推荐)

此方法就是相当于反编译,拿到当时打镜像时候你做的详细操作。比较麻烦,但是是最靠谱的,最具有操作性的。

先将镜像保存为tar文件,命令如下:

1
docker save -o {name}.tar {镜像地址}:{tag}

下载后就会有一个tar包在本地,然后就解压出来。可以看一下manifest.json文件的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[
{
"Config": "dca33100e3683d6fb4d56a4c142ccccc1c113f061454a64bc07c852fe068ea1d.json",
"RepoTags":
[
"{镜像地址}:{tag}"
],
"Layers":
[
"216168069a5195a9424b3a73a62bda39e4d5f8dcae2f7149a336c2e29beeb06b/layer.tar",
"4b0e1f4bede4cef5dee11aff78ff89f543dc62eb02306db1b96d896b101e069d/layer.tar",
"3fe7f20416fdd4958cc18b6fb0d28881147246c32677d102a431c31bf12288f7/layer.tar",
"84c1758c9c15f83d8aa4e1ad13c2918aea80f802f01d19eeb2f7c6e1897d7160/layer.tar",
"31bf0d828ecc19f178d8337e1c22a030984e9185e805b48ea911bd866730af2f/layer.tar",
"7b30e9a6f195343744ca82c66d31b61771e8d6502a271ad60deb1fa1103e83ca/layer.tar",
"522ee848bbd06c6e4dad8d5200b83c9197ccce717fb09687b435190d287f6829/layer.tar",
"a64965663d7c30ed09d35f05439dcfb6247f030df0d72a0e78f54fb6ae5a8c74/layer.tar",
"a93f0f89669c097497a3e3de7aeffebeba2838f180e4f13844be55fe124885ae/layer.tar",
"fd69896888f7361654ed0e27ed2634311b6707dd20706487e33e24f32bb23ebe/layer.tar",
"69c55c418aba5b8fb5239b4e8b092e02100f4ec49dae8ded9cc0a161b21884d7/layer.tar",
"5ef51ffa437403d5d33a40208c3781ea84a93f53947e5d7fad086092667bd3b1/layer.tar"
]
}
]

图片是解压后的效果,里面都会存在一个layer.tar,这里再解压就是当时打镜像时候的一些资源文件。

http://static.cyblogs.com/image-20210928200049751.png

http://static.cyblogs.com/image-20210928200334841.png

红色的部分就是我们想要的内容。再辛苦一点,把自己想要的东西整理出来。描述的比较轻描淡写,任何事情只要手动去做一遍,就会理解与记住。

参考地址

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员微信号:chengcheng222e,他会拉你们进群。

简栈文化服务订阅号