如何检索 Docker 镜像中已添加然后删除的文件?

如何检索 Docker 镜像中已添加然后删除的文件?

假设您有一个像这样的工作目录:

$ 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

答案1

有没有一种方法(或几种方法)从图像中检索在中间层中添加然后删除的 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 命令的结果。鉴于 about 输出,我可以运行:

$ 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

假设使用存储驱动程序的默认 Docker 配置overlay2,您将在/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存储驱动程序(这是当今大多数(如果不是全部)平台上的默认驱动程序)。如果您使用不同的驱动程序,磁盘上的布局将会不同。

相关内容