假设有可能将不同的docker图像层拼接起来吗?

4ioopgfo  于 2023-01-08  发布在  Docker
关注(0)|答案(1)|浏览(68)

我很想多了解一点docker图像的结构,我知道它在docker build环境中是如何工作的:构建文件中的每一步都在最后一步的基础上创建新的层,并且X1 M1 N1 X子句和层高速缓存都意味着层在图像之间被重用。
我还知道,使用overlayfs或类似的方法可以有效地合成层,更改会导致编辑/新建/删除的文件在每个层中存储整个文件或中断文件。
我不知道的是这些层是如何绑定在一起的,不知道每一层中是否有一个对其父层的反向引用,也不知道层的顺序是否由单独保存的元数据定义。

我特别好奇的是,是否假设可以从不相关的图像中提取图层,并将它们拼接成一个新的(工作)图像?。也就是说,在不创建副本并将副本存储在Docker存储库中的情况下拼接它们。您可以假设不相关的图像是为此目的而构建的。

  • 注意:这不是XY问题。我真诚地想知道这个问题的答案,因为我想知道 *
btxsgosb

btxsgosb1#

Docker必须知道将它们组合到容器中的顺序。有些东西知道层的顺序。
没错,该信息由image manifest提供,它是一个JSON文件,其中包含一个有序的层列表以及其他信息。
比如我们来看一下官方的postgres:15图片,我们可以这样抓取内容进行检查:

mkdir postgres-image
docker image save postgres:15 | tar -C postgres-image -xf-

这让我们:

$ ls postgres-image
1c035120f97a959821c3d682e5ddb1b826410b01f1a66ef71426085d11abbac2
1cde06c3f46bf13f0d87eeacc400abc4b80283952c96a0f586a3c4dbc53dea8d
4c6b3cc10e6bbb2afd68caa44a3eb6cef12caf483e60b28c6de2c56e8f1b99bc.json
586bebe8d837fb5b377b572f83f88d65c3c667624edf6230951a4a714c2d879b
7de3bcc2590b6a6bdf63c49e4861b2d44234de5aff1017c982b51ae8343a8f9d
866914886a5c213ca953042f6d9f15a2a803ef8318321651f45552aff0910d9b
9ec9c81974bf829a515052eb4a318630bcaf43abd02bf4e59703f796fc5df66d
a2036affeb348540e00efc39a5bc8e8f099327725b0e81ce068c4e55ac76cb50
aea69f9cbe92ef8c8efd388c69e169f036070c8ab068acf993cf9096010e4191
d10e11a29048914235b611ff7a0c93ebb529b1d1f8f0e00f883a341f0193d9ab
d24fc4b0912a24f160d52cf9273bf07f0ca18ed0ae1855e41e4c1cbefa650dd5
e72ed9131fa5b904acf7bcfe7978f97e99c9fb087308b7cefd5063edea0bf7b8
eaf7c4940ac93309a059cc3f91f847a130317a98c7380e0534b2c525c8e805a3
fc5484c1b2ce93576cc100282c8e446581c5ffd48e6199a8b2d651d7f9171124
manifest.json
repositories

清单文件包含在manifest.json中,如下所示:

[
  {
    "Config": "4c6b3cc10e6bbb2afd68caa44a3eb6cef12caf483e60b28c6de2c56e8f1b99bc.json",
    "RepoTags": [
      "postgres:15"
    ],
    "Layers": [
      "fc5484c1b2ce93576cc100282c8e446581c5ffd48e6199a8b2d651d7f9171124/layer.tar",
      "d10e11a29048914235b611ff7a0c93ebb529b1d1f8f0e00f883a341f0193d9ab/layer.tar",
      "a2036affeb348540e00efc39a5bc8e8f099327725b0e81ce068c4e55ac76cb50/layer.tar",
      "1cde06c3f46bf13f0d87eeacc400abc4b80283952c96a0f586a3c4dbc53dea8d/layer.tar",
      "7de3bcc2590b6a6bdf63c49e4861b2d44234de5aff1017c982b51ae8343a8f9d/layer.tar",
      "aea69f9cbe92ef8c8efd388c69e169f036070c8ab068acf993cf9096010e4191/layer.tar",
      "586bebe8d837fb5b377b572f83f88d65c3c667624edf6230951a4a714c2d879b/layer.tar",
      "9ec9c81974bf829a515052eb4a318630bcaf43abd02bf4e59703f796fc5df66d/layer.tar",
      "1c035120f97a959821c3d682e5ddb1b826410b01f1a66ef71426085d11abbac2/layer.tar",
      "e72ed9131fa5b904acf7bcfe7978f97e99c9fb087308b7cefd5063edea0bf7b8/layer.tar",
      "eaf7c4940ac93309a059cc3f91f847a130317a98c7380e0534b2c525c8e805a3/layer.tar",
      "d24fc4b0912a24f160d52cf9273bf07f0ca18ed0ae1855e41e4c1cbefa650dd5/layer.tar",
      "866914886a5c213ca953042f6d9f15a2a803ef8318321651f45552aff0910d9b/layer.tar"
    ]
  }
]

Docker就是通过这个图层列表知道如何合成最终图像的:你从第一层开始,然后在它上面应用每个后续层。
我不知道每个层中是否有一个对其父层的反向引用,或者层的顺序是否由单独保存的元数据定义。
答案是“两者都有”。顺序由清单中的层列表定义,但每个层也包含对其父层的引用。例如,如果我们查看文件1cde06c3f46bf13f0d87eeacc400abc4b80283952c96a0f586a3c4dbc53dea8d/json,我们会看到:

{
  "id": "1cde06c3f46bf13f0d87eeacc400abc4b80283952c96a0f586a3c4dbc53dea8d",
  "parent": "a2036affeb348540e00efc39a5bc8e8f099327725b0e81ce068c4e55ac76cb50",
  "created": "1969-12-31T19:00:00-05:00",
  "container_config": {
    "Hostname": "",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": null,
    "Cmd": null,
    "Image": "",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "os": "linux"
}

属性parent是对上一图层的引用。

相关问题