【編者的話】當(dāng)我們想讓一個(gè)容器做兩件事情,或者使一個(gè)Docker鏡像包含來(lái)自兩個(gè)不同鏡像的依賴庫(kù)時(shí),我們就需要知道每個(gè)鏡像的Dockerfile。本文介紹了如何通過(guò)
docker history
命令來(lái)對(duì)Docker鏡像進(jìn)行反向工程,得到它們的Dockerfile,并組織到一個(gè)Dockerfile里然后build,從而實(shí)現(xiàn)我們想做的事情。
常言道,“不要重復(fù)發(fā)明輪子!”
在使用Docker時(shí),構(gòu)建自己的鏡像之前,最好在
Docker Hub尋找一些可以直接使用的鏡像做練習(xí)。把你的軟件架構(gòu)分布到一系列容器中,每一個(gè)容器只做一件事情,這樣的效果非常好。構(gòu)建分布式應(yīng)用的最好的基石是使用來(lái)自Docker Hub的官方鏡像,因?yàn)槟憧梢孕湃嗡鼈兊馁|(zhì)量。
在某些情況下,你可能想讓一個(gè)容器做兩件不同的事情。而在另外一些情況下,你可能想讓一個(gè)Docker鏡像包含來(lái)自兩個(gè)不同鏡像的依賴庫(kù)。如果你有每個(gè)鏡像的Dockerfile,這是非常簡(jiǎn)單的。將它們組織到一個(gè)Dockerfile里然后build就行。
然而,大多數(shù)時(shí)間你都在使用Docker Hub上準(zhǔn)備好的鏡像,你不會(huì)有它們的源Dockerfile。我花時(shí)間找一個(gè)可以合并(或flatten)兩個(gè)不同Docker鏡像的工具,當(dāng)然我沒(méi)有它們的Dockerfile。也就是說(shuō)我在找一個(gè)能做下面這件事的東西:
image 1 --
\
---> merged_image_12
/
image 2 --
此前在GitHub上有兩個(gè)相關(guān)的討論(
1、
2),盡管它們都被關(guān)閉了。
這可能嗎?
那么,是否存在工具能夠像這樣做嗎:
docker merge image2 image2 merged_image
?
沒(méi)有!
你甚至不可以用下面的方式來(lái)構(gòu)建Dockerfile:
FROM image1
FROM image2
簡(jiǎn)而言之,在一個(gè)Dockerfile里不能有多個(gè)基礎(chǔ)鏡像。
但是我需要這個(gè)功能!
唯一的解決辦法是取得這些鏡像的Dockerfile,然后把它們組織到一個(gè)文件中,再進(jìn)行構(gòu)建。那么,我能在Docker Hub上獲得一個(gè)鏡像的Dockerfile嗎? 幸運(yùn)的是可以。它不能離線獲取(譯注:原文是online,但顯然online時(shí)對(duì)于來(lái)自GitHub的自動(dòng)構(gòu)建鏡像是可以直接獲取的),但是你可以使用
docker history
命令,通過(guò)反向工程獲取。
怎么來(lái)使用?
在你的機(jī)器上使用
docker pull
從Docker Hub下載鏡像。
docker pull image1
docker pull image2
然后使用
docker history
來(lái)取得構(gòu)建這兩個(gè)容器時(shí)運(yùn)行的命令。
docker history --no-trunc=true image > image1-dockerfile
docker history --no-trunc=true image2 > image2-dockerfile
接下來(lái)打開(kāi)這兩個(gè)文件,你可以看到每個(gè)鏡像的命令堆棧。這是因?yàn)镈ocker鏡像通過(guò)層(
閱讀更多)的方式來(lái)構(gòu)建。即你在Dockerfile中鍵入的每一個(gè)命令所構(gòu)建的新鏡像,都是在之前的命令產(chǎn)生的鏡像之上。所以你可以對(duì)鏡像進(jìn)行逆向工程。
限制
你不能對(duì)鏡像進(jìn)行反向工程的唯一場(chǎng)景,是鏡像的維護(hù)者在他的Dockerfile中使用了
ADD
或
COPY
命令。你會(huì)看到這樣一行:
ADD file:1ac56373f7983caf22
或 ADD dir:cf6fe659e9d21535844
這是因?yàn)槟悴恢谰S護(hù)者在他自己的機(jī)器上,包括鏡像里使用了什么本地文件。
Happy Reverse-Engineering
原文鏈接:How to Merge Two Docker Images(翻譯:陳光 審校:魏小紅)