当前位置: 首页 > 知识库问答 >
问题:

如何将docker图像链接到磁盘上的组成层?

汝繁
2023-03-14

自从Docker v1.10引入内容可寻址存储以来,Docker已经完全改变了磁盘上处理图像数据的方式。我明白了,现在图层和图像是分开的。图层仅仅是没有图像概念的文件和目录的集合,可以在图像之间自由共享。看到更新和博客有更好的解释。

docker pushdocker pull期间,可以通过标准输出看到层被传输,尽管生成的SHA哈希在目的地上完全重新生成。

使用ubuntu:14.04base本地构建的映像,当我使用docker history命令时,我可以看到构建过程中使用的一系列中间映像,以及它们所贡献的磁盘空间使用情况。

root@ruifeng-VirtualBox:/var/lib/docker/aufs/diff# docker history image_size
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
9ae1f372d83c        11 weeks ago        /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin/   0 B                 
aaf66e9fa85b        11 weeks ago        /bin/sh -c chown -R martian /home/martian       6.299 MB            
9568768134c1        11 weeks ago        /bin/sh -c rm -rf /home/martian/potatoes        0 B                 
2f40f3f58306        11 weeks ago        /bin/sh -c mv /home/martian/water_tanks /home   6.289 MB            
062e2702ffa2        11 weeks ago        /bin/sh -c mv /home/martian/potatoes /home/ma   5.394 kB            
7b2d8b4c1dd0        11 weeks ago        /bin/sh -c chown -R martian /home/martian       6.299 MB            
8fd47fed98d6        11 weeks ago        /bin/sh -c #(nop) COPY dir:421da6c71a1f252881   6.289 MB            
...

我可以使用docker inspect命令来获取底层。

root@ruifeng-VirtualBox:/var/lib/docker/aufs/diff# docker inspect image_size | jq -r '.[].RootFS'
{
  "Layers": [
    "sha256:a85f35566a268e6f4411c5157ffcffe4f5918b068b04d79fdd80003901ca39da",
    "sha256:eaaf7298332642da0f8190fa4b96ad46c04b9c1d1682bc3a35d77bded2b1e0a9",
    "sha256:33a212e8aa5642d3a2ddead146e85912407fc5bbb2a896dab11fcf329177a999",
    "sha256:f1f25d8c6e56dc4891df147a77f57e756873b57f33ce95e6a0acbe47117c0c8a",
    "sha256:67852b7d2cf5f0885293fa9df91ebfd8ef0c42ba11a5155f94806f3a96c5e916",
    "sha256:480d48b7e2864a44c1b2fca0c7e32fbab505f7526ccb25bbfed191c04a9bb7b0",
    "sha256:18d270fe64aa423e0ffdf24faf0103432027da3d5c12f4505e7daedad9fe2195",
    "sha256:a73c3f5eb83790bc6d03381a43a20aef7d0d9d97de0cff4b040e8e4c01a3aee5",
    "sha256:e8d1b67ace73cb92cc00725354e84024153bedae4280149c03fcb52f34d83757",
    "sha256:19a4b80afc677825fec94adf8b6a45a866f42a38675f87f86e50171ff5e0a280",
    "sha256:77d412270fbdd9baba1fe73028b786c3a1709feefa9b03be74b8e9f9ce148635",
    "sha256:2ad21e37389addd577161c981d0c69ab60aa47945172f41f9ec71ada1c1dd4ee",
    "sha256:771d1e47ca8d8dcf55069786e4c499894fba86f704c808413df00f4f980564e1",
    "sha256:f9c02c6fa436213c0f220d49c4ee1b913372081010d4506757ec75d3e788847c"
  ],
  "Type": "layers"
}

我的问题是,如何将这些用SHA哈希标记的层链接到上一个命令输出的IMAGE列中列出的图像?有没有办法找出磁盘上这些层的实际位置和大小?

如果我没有错,那么如果存储驱动程序选择是aufs,那么层应该保持在/var/lib/docker/aufs/diff。但该文件夹中的内容是用随机生成的ID命名的,这些ID与任何层都不匹配。似乎出于安全考虑,Docker引擎中只保留了匹配项。

共有3个答案

朱兴学
2023-03-14

如果这是一个vfs,可以用下面的一行来完成:

ls -l /var/lib/docker/vfs/dir/$(cat $(grep $LAYER /var/lib/docker/image/vfs/layerdb/sha256/ -rl | sed s/diff/cache-id/g ))

其中,$LAYER是从docker inspect IMAGE\u ID

杜弘伟
2023-03-14

根据larsks在答案中给出的灵感,我设法找到了图层的位置。

例如,假设我们想要找到由复制步骤提供的层的位置,该步骤对应于id为8fd47fed98d6的中间图像,我们可以首先检查它。

root@ruifeng-VirtualBox:/var/lib/docker# docker inspect 8fd47fed98d6 | jq -r '.[].RootFS'
{
  "Layers": [
    "sha256:a85f35566a268e6f4411c5157ffcffe4f5918b068b04d79fdd80003901ca39da",
    "sha256:eaaf7298332642da0f8190fa4b96ad46c04b9c1d1682bc3a35d77bded2b1e0a9",
    "sha256:33a212e8aa5642d3a2ddead146e85912407fc5bbb2a896dab11fcf329177a999",
    "sha256:f1f25d8c6e56dc4891df147a77f57e756873b57f33ce95e6a0acbe47117c0c8a",
    "sha256:67852b7d2cf5f0885293fa9df91ebfd8ef0c42ba11a5155f94806f3a96c5e916",
    "sha256:480d48b7e2864a44c1b2fca0c7e32fbab505f7526ccb25bbfed191c04a9bb7b0",
    "sha256:18d270fe64aa423e0ffdf24faf0103432027da3d5c12f4505e7daedad9fe2195",
    "sha256:a73c3f5eb83790bc6d03381a43a20aef7d0d9d97de0cff4b040e8e4c01a3aee5",
    "sha256:e8d1b67ace73cb92cc00725354e84024153bedae4280149c03fcb52f34d83757",
    "sha256:19a4b80afc677825fec94adf8b6a45a866f42a38675f87f86e50171ff5e0a280"
  ],
  "Type": "layers"
}

现在我们尝试寻找最后一层。

root@ruifeng-VirtualBox:/var/lib/docker# find . -name '*19a4b80afc677825fec94adf8b6a45a866f42a38675f87f86e50171ff5e0a280*'
root@ruifeng-VirtualBox:/var/lib/docker# 

但是磁盘上什么也没有。也许那里有一些参考树。我们可以检查layerdb中的文件内容。

root@ruifeng-VirtualBox:/var/lib/docker# grep -rl 19a4b80afc677825fec94adf8b6a45a866f42a38675f87f86e50171ff5e0a280 image/aufs/layerdb/
image/aufs/layerdb/sha256/f1824ce70e6d1e8f140b9ba637b7447c00d8158d3bbc1f72b491766ab54dd449/diff

我们可以看到该层实际上是一个difff1824ce70e6d1e8f140b9ba637b7447c00d8158d3bbc1f72b491766ab54dd449。让我们找到它。

root@ruifeng-VirtualBox:/var/lib/docker# find . -name '*f1824ce70e6d1e8f140b9ba637b7447c00d8158d3bbc1f72b491766ab54dd449*'
./image/aufs/layerdb/sha256/f1824ce70e6d1e8f140b9ba637b7447c00d8158d3bbc1f72b491766ab54dd449 

并找到缓存id,它将引导我们进入aufs/diff文件夹中的实际位置。

root@ruifeng-VirtualBox:/var/lib/docker# cat image/aufs/layerdb/sha256/f1824ce70e6d1e8f140b9ba637b7447c00d8158d3bbc1f72b491766ab54dd449/cache-id 
c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637

让我们去那个地方看看。

root@ruifeng-VirtualBox:/var/lib/docker# cd aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637
root@ruifeng-VirtualBox:/var/lib/docker/aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637# find .
.
./home
./home/martian
./home/martian/water_tanks
./home/martian/water_tanks/IMG_0052.JPG
root@ruifeng-VirtualBox:/var/lib/docker/aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637#

它包含通过COPY步骤复制到映像中的所有文件和目录。层的大小也可以检查。

root@ruifeng-VirtualBox:/var/lib/docker# du -sh aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637
6.1M    aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637

如果后续层也以相同的方式进行检查,那么这将提供对Union文件系统和Docker使用的写时拷贝机制的一些深入了解。

这也可以按相反的顺序进行。我们可以查找要位于映像内部的文件或目录,该文件或目录应该位于aufs/diff中的某个位置,然后使用缓存id追溯到层。

root@ruifeng-VirtualBox:/var/lib/docker# find . -name '*water_tanks*'
./aufs/diff/c097799b7946231fb60511b442c10cd0b56ee17a12b376149f305adda67e7637/home/martian/water_tanks
邵骏喆
2023-03-14

似乎出于安全考虑,Docker引擎中只保留了匹配项。

显然,它必须存储在磁盘上的某个地方,因为信息需要持久性。我使用的是overlay2驱动程序,而不是aufs,但我猜布局相对类似。让我们从我在本地看到的图像开始:

# docker images | grep alpine
alpine                                              latest              baa5d63471ea        5 months ago        4.8 MB

其具有以下层:

# docker inspect alpine | jq '.[0].RootFS'
{
  "Type": "layers",
  "Layers": [
    "sha256:011b303988d241a4ae28a6b82b0d8262751ef02910f0ae2265cb637504b72e36"
  ]
}

让我们在/var/lib/docker中查找与图像id前缀匹配的内容:

# cd /var/lib/docker
# find . -name 'baa5d63471ea*' -print
./image/overlay2/imagedb/content/sha256/baa5d63471ead618ff91ddfacf1e2c81bf0612bfeb1daf00eb0843a41fbfade3

这是一个包含一堆数据的JSON文件,其中包括一些看起来相关的内容:

  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:011b303988d241a4ae28a6b82b0d8262751ef02910f0ae2265cb637504b72e36"
    ]
  }

伟大的使用这些信息,我们应该能够获取一个图层id并找到使用它的所有图像。例如,我有一个本地构建的映像,看起来像:

# docker inspect larsks/qgroundcontrol | jq '.[0].RootFS'
{
  "Type": "layers",
  "Layers": [
    "sha256:c854e44a1a5a22c9344c90f68ef6e07fd479e8ce1030fe141e3236887f1a4920",
    "sha256:8ba4b4ea187c5ea58c11ee99bbc159b88b303c290b18c2220c9b477f4427bb9e",
    "sha256:46c98490f5756634de1b1b9ed02a9fae2732984049f4f8fa182959fea924a45c",
    "sha256:1633f88f8c9fa73c5c0c24f314e81b10dda6c310d41fb87eba02421e1652f6dc",
    "sha256:0e20f4f8a593705219d1b3c5b1d2f7b8664eb04d706e99add87adbdcceea4a9f",
    "sha256:cb16829cadf4f4320799bdf23f7400816f1552a011f3e30c2c929382896c3f6f",
    "sha256:5e6951567308b8aacd8f6bded126ab33a72e7aa584d012a8d0d6283c29d32995",
    "sha256:66a1378b08992e4043cf4e391d5b7f52f0d8c4b825dc62a2d87c23ba6ea1dd35",
    "sha256:d397a7c12cc95021d41059a44c137000dfcbf12e6ba295ccb647c075e368e39c",
    "sha256:8a2c46060eadf56c93467f9445cc49a715a935b0e3b4b439ae8c00fcf3a2157b",
    "sha256:70a195ccb5fc7423cc15dd55fb446a19bfd2e1d1a4e5132b79f9433b7d7df750",
    "sha256:349fbf13a3797683fe9a2c8355df2a272da391efab8e11c9e083e3c95c094859"
  ]
}

让我们查找包含相同基本层的其他图像列表(sha256:c854e44a1a5a22c9344c90f68ef6e07fd479e8ce1030fe141e3236887f1a4920):

# cd /var/lib/docker
# grep -rl sha256:c854e44a1a5a22c9344c90f68ef6e07fd479e8ce1030fe141e3236887f1a4920 image/overlay2/imagedb/

这将返回类似于:

image/overlay2/imagedb/content/sha256/d404c11f391c3588ad665fa9ad3f779eb56efc1abbed3cf309b834c824d3c93f
image/overlay2/imagedb/content/sha256/dc3313d83519292279466fb5ee7913350d49b8d82f85d537b713ca83d75049e7
image/overlay2/imagedb/content/sha256/dda2981c2844dd1c4a5e004d8bc14633b445f61d23312abba8468251389ed0bc
image/overlay2/imagedb/content/sha256/e865d00f6e1e56e7efcfcaf111c52064fc732e68de3eace195492ebf66c7bc74
image/overlay2/imagedb/content/sha256/ea697b65eff199541ec38bbf6ee28085463f0679c9aec3867834f0c14d29d6f4

这是包含相同图层的图像标识列表。如果我想将这些id映射回名称,我需要参考Image/overlay2/repositories.json,它将名称映射到层,或者我需要解析docker图像的输出。也许是这样的:

grep -rl sha256:c854e44a1a5a22c9344c90f68ef6e07fd479e8ce1030fe141e3236887f1a4920 image/overlay2/imagedb/  |
while read path; do 
  id=${path##*/}
  docker images --no-trunc | grep $id | awk '{print $1, $3}'
done

我的系统会输出:

larsks/mavproxy sha256:0af8d29ecea9dc870ba0a7740d9f23a55aad8d9edacf4f89f6d6b239b58c7829
larsks/apmplanner sha256:5e715eb065698db5444af5ff341d30007d0b67507885f8aab89701ec2c4731fe
larsks/qgroundcontrol sha256:2a6265c23c52d1842ac38ea78fde670910dd40d15a8f0f62f60646ad9b209542
sitl sha256:7420866bd587f7b76fbd23b1c15d0a2b9ca5a04fd2d6e442c62a6b25a195b378
cmd/mavproxy sha256:d00e9707a3d8b1cae319ec88b4ccb26f111bb979ec1978cd32147274ab1704e4
cmd/apmplanner sha256:d17cae44602ad335f518276dfcc8a27a251b619f3f9037c55c278eb49d83d74b
cmd/qgroundcontrol sha256:d404c11f391c3588ad665fa9ad3f779eb56efc1abbed3cf309b834c824d3c93f
mavproxy sha256:dda2981c2844dd1c4a5e004d8bc14633b445f61d23312abba8468251389ed0bc
ubuntu sha256:f753707788c5c100f194ce0a73058faae1a457774efcda6c1469544a114f8644

...这似乎很合理。

 类似资料:
  • 我们注意到我们的容器占用了很多空间,其中一个原因是图像。 我们想移动图像。 我知道现在它们存储在

  • 问题内容: 我的Express应用程序正在从浏览器中接收base64编码的PNG(使用toDataURL()从画布生成)并将其写入文件。但是该文件不是有效的图像文件,因此“文件”实用程序只是将其标识为“数据”。 问题答案: 我认为您正在转换的数据比您需要的更多。一旦使用正确的编码创建了缓冲区,您只需要将缓冲区写入文件即可。 new Buffer(…,’base64’)通过将输入解释为base64编

  • 问题内容: 我有一个小的PyGI项目,它使用开罗图像表面,然后使用表面图案缩放并在Gtk.DrawingArea上进行渲染。 我想将 缩放后的 版本写入PNG文件。我尝试使用Surface.write_to_png()从原始表面进行写操作,但是它仅以原始(即非缩放)大小进行写操作,因此我被困在那里。 然后我想我也许可以从Gtk.DrawingArea中获取渲染的图像并将其写入磁盘,但是我还没有找到

  • 本文向大家介绍如何将图像用作HTML中的链接?,包括了如何将图像用作HTML中的链接?的使用技巧和注意事项,需要的朋友参考一下 要将图像用作HTML中的链接,请使用<img>标记以及带有href属性的<a>标记。<img>标记用于在网页中使用图像,<a>标记用于添加链接。在图片标签src属性下,添加图片的网址。这样,还可以添加高度和宽度。 示例 您可以尝试运行以下代码以将图像用作HTML中的链接

  • 问题内容: 我试图捕获与表单一起发送的文件,并在对其进行保存之前对其执行一些操作。因此,我需要在temp目录中创建此文件的副本,但是我不知道如何到达它。Shutil的功能无法复制此文件,因为没有路径。那么,是否有其他方法可以执行此操作? 我的代码: 引起: 和调试: 问题答案: 这是类似的问题,可能会有所帮助。