假设您有一个像这样的工作目录:
$ 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
存储驱动程序(这是当今大多数(如果不是全部)平台上的默认驱动程序)。如果您使用不同的驱动程序,磁盘上的布局将会不同。