【编者的话】本文介绍了如何通过 docker history
命令来对docker 镜像进行反向工程推测它们的Dockerfile,从而在对不同的Docker 镜像反向工程获取Dockerfile 之后合并成一个。
常言道,“不要重复发明轮子!”
在使用docker 时,最好在构建你自己的镜像前上 Docker Hub 寻找一些直接可以用的。把你的软件架构分布到一系列容器中,每一个容器只做一件事情是非常有用的。构建分布式应用的最好的基石是使用来自Docker Hub 的官方镜像,因为你可以信任它们的质量。
在某些情况下,你可能想让一个容器做两件不同的事情。在另一些情况下,你可能想让一个Docker 镜像包含来自两个不同镜像的依赖。 如果你有每个镜像的Dockerfile,这是非常简单的。将它们组织到一个Dockerfile 里然后build 即可。
但是,如果大多数时间你都在使用Docker Hub 上准备好的镜像,你将没有它们的源Dockerfile。我花了一些时间来找这样一个工具,它可以合并(或flatten)两个不同的我没有它们的Dockerfile 的Docker 镜像。即我在找一个能做下面这件事的东西:
image 1 --
/
---> merged_image_12
/
image 2 --
尽管这个问题在之前的两个进程中被关闭了( 1 , 2 ),当你想这么做时,这个问题仍然会产生。
即有任何工具能够像这样做吗: docker merge image2 image2 merged_image
?
你甚至不能这样来构建一个Dockerfile:
FROM image1
FROM image2
简而言之,你不能在一个Dockerfile 里有多个基础镜像。
唯一的解决办法是取得这些镜像的Dockerfile 然后把它们组织到一个文件中,再进行构建。所以我能在Docker Hub 上取得一个镜像的Dockerfile 吗? 幸运的是可以。 它不能离线获取(译注:原文是online 但显然online 时对于来自Github 的自动构建镜像是可以直接获取的),但是你可以通过 docker history
命令来反向工程获得。
在你的机器上使用 docker pull
来从Docker Hub下载镜像。
docker pull image1
docker pull image2
然后使用 docker history
来取得构建这两个容器时运行的命令。
docker history --no-trunc=true image > image1-dockerfile
docker history --no-trunc=true image2 > image2-dockerfile
接下来打开这两个文件,你可以看到每个镜像的命令堆栈。这是因为Docker 镜像通过层( 阅读更多 )的方式来组织。即每一个你在Dockerfile 中键入的命令都会产生一个从之前的命令产生的镜像之上的一个新镜像。所以你可以对镜像逆向工程。
唯一的你不能够反向工程镜像的场景是镜像的维护者在他的Dockerfile 中使用了 ADD
或 COPY
命令。你会看到这样一行:
ADD file:1ac56373f7983caf22
或 ADD dir:cf6fe659e9d21535844
这是因为你不能知道维护者在他自己的机器上用了什么本地文件在镜像中。
反向工程愉快 :smile:
原文链接: How to Merge Two Docker Images (翻译:陈光)