Docker

如何檢索已在 Docker 映像中添加然後刪除的文件?

  • February 10, 2019

假設您有一個這樣的工作目錄:

$ tree .
.
├── Dockerfile
└── file.txt

並且Dockerfile包含:

FROM debian:9

WORKDIR /usr/src/foo

COPY file.txt .

RUN echo Some random command involving file.txt \
 && rm -f file.txt

然後建構相應的鏡像並將其推送到給定的 Docker 系統資料庫:

$ docker build -t foo/bar .
$ docker login #…
$ docker push foo/bar

有沒有一種方法(或幾種方法)從圖像中檢索,其內容file.txt被添加然後在中間層中刪除?答案是否取決於您的選擇WORKDIR

有沒有一種方法(或幾種方法)從圖像中檢索,添加然後在中間層中刪除的 file.txt 的內容?

是的!

答案是否取決於 WORKDIR 的選擇?

WORKDIR。除了更改目前工作目錄外,不會做任何事情。


當您從 Dockerfile 建構映像時,Dockerfile 中的每個指令都會創建一個新層。“圖像”只是在執行容器時組合形成容器文件系統的層的集合。這些層中的每一層都可以在磁碟上的/var/lib/docker. 例如,假設我使用這個 Dockerfile 建構了一個鏡像:

FROM debian:9
COPY file.txt /root/file.txt
RUN rm -f /root/file.txt

在該目錄中,我有一個名為的文件file.txt,其中包含以下文本:

hello world

如果我執行docker build -t erikmd .,我會看到:

Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM debian:9
---> d508d16c64cd
Step 2/3 : COPY file.txt /root/file.txt
---> Using cache
---> 6f06029c1cca
Step 3/3 : RUN rm -f /root/file.txt
---> Using cache
---> a2dc62c823c9
Successfully built a2dc62c823c9
Successfully tagged erikmd:latest

建構過程中的每一步都會生成一個新層,會為您提供一個表示中間鏡像的鏡像 ID,該中間鏡像是到目前為止所有 Dockerfile 命令的結果。鑑於關於輸出,我可以執行:

$ docker run --rm 6f06029c1cca cat /root/file.txt

並查看文件內容:

hello world

但是,如果我只是建構圖像怎麼辦?在這種情況下,我將首先使用docker image inspect命令查看構成圖像的層列表:

$ docker image inspect erikmd | jq '.[0].RootFS.Layers'
[
 "sha256:13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303",
 "sha256:41494b03ef195ce6db527bd68b89cbebdace66210b4c142e95f8553fcb0bf51e",
 "sha256:1948a4bd00b6f1712667bb2c68d1fe6eb60fbbcdf8bad62653208c23bf2602a5"
]

在上面,jq只是一個查詢JSON數據的工具。docker image inspect如果您碰巧不方便,您可以直覺地檢查相同資訊的輸出jq

假設使用overlay2儲存驅動程序的預設 Docker 配置,您將在/var/lib/docker/image/overlay2/layerdb/sha256/*/diff. 因此,例如:

# grep -l 13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303 \
 /var/lib/docker/image/overlay2/layerdb/sha256/*/diff
/var/lib/docker/image/overlay2/layerdb/sha256/13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303/diff

第一層是debian:9圖像。我們可以通過執行來確認:

$ docker image inspect debian:9 | jq '.[0].RootFS.Layers'
[
 "sha256:13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303"
]

…所以我們將忽略它。讓我們找到第二層:

# grep -l 41494b03ef195ce6db527bd68b89cbebdace66210b4c142e95f8553fcb0bf51e \
 /var/lib/docker/image/overlay2/layerdb/sha256/*/diff
/var/lib/docker/image/overlay2/layerdb/sha256/14347a192896a59fdf5c1a9ffcac2f93025433c66136d3531d7bbb3aec53efc7/diff

在與該diff文件相同的目錄中,我們將找到一個名為cache-id

# cat image/overlay2/layerdb/sha256/14347a192896a59fdf5c1a9ffcac2f93025433c66136d3531d7bbb3aec53efc7/cache-id
118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75

標識cache-id層已被提取到的目錄;我們可以在下面找到它/var/lib/docker/overlay2/<id>

# ls /var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75
diff/ link lower work/

我們對diff/目錄的內容感興趣:

# find /var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef6
21ccb70cf14fe672dc74ef75/diff/
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/root
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/root/file.txt

它就在那裡!


注意以上所有內容都假設您正在使用overlay2儲存驅動程序(這是當今大多數平台(如果不是所有平台)的預設設置)。如果您使用不同的驅動程序,磁碟上的佈局將有所不同。

引用自:https://unix.stackexchange.com/questions/499713