简体   繁体   English

docker:从图像中提取图层

[英]docker: extracting a layer from a image

Let's take the whalesay images as an example.让我们以whalesay 图像为例。 docker history shows the following: docker history显示如下:

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
6b362a9f73eb        17 months ago       /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/us   0 B
<missing>           17 months ago       /bin/sh -c sh install.sh                        30.37 kB
<missing>           17 months ago       /bin/sh -c git reset --hard origin/master       43.27 kB
<missing>           17 months ago       /bin/sh -c #(nop) WORKDIR /cowsay               0 B
<missing>           17 months ago       /bin/sh -c git clone https://github.com/moxie   89.9 kB
<missing>           17 months ago       /bin/sh -c apt-get -y update && apt-get insta   58.58 MB
<missing>           18 months ago       /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
<missing>           18 months ago       /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/   1.895 kB
<missing>           18 months ago       /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic   194.5 kB
<missing>           18 months ago       /bin/sh -c #(nop) ADD file:f4d7b4b3402b5c53f2   188.1 MB

I'd like to extract the layer that says ADD file:bla .我想提取显示ADD file:bla的图层。 Is there a tool/way for doing this?有没有这样做的工具/方法?

In this specific case, it looks like the ADD command added the base image to the file system. 在这种特定情况下,看起来ADD命令将基本映像添加到文件系统。 If you run docker history --no-trunc docker/whalesay , the full command is: 如果您运行docker history --no-trunc docker/whalesay ,则完整命令为:

/bin/sh -c #(nop) ADD file:f4d7b4b3402b5c53f266bb7fdd7e728493d9a17f9ef20c8cb1b4759b6e66b70f in /

docker history reports that particular layer is 188MB. docker history报告特定图层为188MB。 Let's look at these layers in more detail: 让我们更详细地看一下这些层:

$ docker save docker/whalesay -o whalesay.tar
$ tar tvf whalesay.tar

...
-rw-r--r-- 0/0       197181952 2015-05-25 22:04 cc88f763e297503d2407d6b462b2b390a6fd006b30f51c8efa03dd88fa801b89/layer.tar
...

Looks like a pretty good candidate! 看起来像个不错的候选人! You can now extract that layer and pull files out of it. 您现在可以提取该图层并从中提取文件。

$ tar xf whalesay.tar cc88f763e297503d2407d6b462b2b390a6fd006b30f51c8efa03dd88fa801b89/layer.tar
$ tar xf cc88f763e297503d2407d6b462b2b390a6fd006b30f51c8efa03dd88fa801b89/layer.tar etc/passwd

If you're looking to pull a particular file out of a layer, but you don't know which layer, you could do this. 如果您想要从图层中提取特定文件,但是您不知道哪个图层,则可以执行此操作。 First, extract all the layers: 首先,提取所有图层:

$ tar xf whalesay.tar

Now you've got all the layers as individual .tar files. 现在你已经将所有图层都作为单独的.tar文件。 Let's find a file: 我们找一个文件:

$ for layer in */layer.tar; do tar -tf $layer | grep docker.cow && echo $layer; done
usr/local/share/cows/docker.cow
0523c5a0c4588dde33d61d171c41c2dc5c829db359f4d56ab896ab1c185ed936/layer.tar
cowsay/cows/docker.cow
40e8ae7bb4e5b9eaac56f5be7aa614ed50f163020c87ba59e905e01ef0af0a4f/layer.tar
cowsay/cows/docker.cow
f9bc8676543761ff3033813257937aeb77e9bc84296eaf025e27fe01643927cf/layer.tar

Finally, extract the file from the layer you want: 最后,从您想要的图层中提取文件:

$ tar xf 0523c5a0c4588dde33d61d171c41c2dc5c829db359f4d56ab896ab1c185ed936/layer.tar \
      usr/local/share/cows/docker.cow

This will extract that file with the full path relative to the current directory. 这将使用相对于当前目录的完整路径提取该文件。

$ cat usr/local/share/cows/docker.cow 
##
## Docker Cow
##
$the_cow = <<EOC;
    $thoughts
     $thoughts
      $thoughts     
                    ##        .            
              ## ## ##       ==            
           ## ## ## ##      ===            
       /""""""""""""""""\___/ ===        
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
       \\______ o          __/            
        \\    \\        __/             
          \\____\\______/   
EOC

It looks like other people would also like to have this feature, but unfortunately right now it does not seem to exist. 看起来其他人也想拥有这个功能,但不幸的是现在它似乎并不存在。

See also this issue and here a related request which got rejected. 另请参阅此问题 ,此处有相关请求被拒绝。

If you're fine with saving the complete docker ( docker save ) and then extracting a tarball with your layer, then this is possible: 如果您可以保存完整的docker( docker save ),然后使用您的图层提取tarball,那么这是可能的:

docker run -it <your image>
# do fancy stuff in the container
docker commit <your container> foobar # create image from container
docker history foobar # will show you the layers
docker save -o foobar.tar foobar # dumps container contents to foobar.tar

Now foobar.tar will contain the file system states from different times. 现在foobar.tar将包含来自不同时间的文件系统状态。 Inspecting this tarball shows, in my case, a file repositories with 在我的例子中,检查这个tarball显示了一个文件repositories

{"foobar":{"latest":"fdf43d96e691c57e9afb4b85dba2e6745146a7ca9076c7284c6b2e1f93434562"}}

which indicates, that the latest layer is fdf43... . 表示最新的图层是fdf43... You can get a tarball with the file system contents of this layer via 您可以通过此层的文件系统内容获取tarball

tar -x fdf43d96e691c57e9afb4b85dba2e6745146a7ca9076c7284c6b2e1f93434562/layer.tar -f foobar.tar

There is a tool, undocker , which automated this process, but I'm not sure whether it will work with the current format of the saved tar file. 有一个工具, undocker ,它自动化这个过程,但我不确定它是否适用于保存的tar文件的当前格式。

I don't really understand what you mean by "extract" but if you want to get further information about image, run 我真的不明白你的意思是“提取”,但如果你想获得有关图像的更多信息,请运行

docker inspect <image_name>

You you want to get file, then run container from this image. 您想要获取文件,然后从此图像运行容器。 Try 尝试

docker export <container_name> > abc.tar

after that, extract abc.tar and find your file. 之后, 提取 abc.tar并找到您的文件。

The regclient/regclient project does include a regctl blob /regctl later which allows to fetch a specific layer. regclient/regclient项目确实包含一个regctl blob /regctl later ,它允许获取特定层。

You can list layers with regctl image manifest .您可以使用regctl image manifest列出图层。

Since regctl v0.4.5 , you can even use ( PR 296 ):由于regctl v0.4.5 ,您甚至可以使用( PR 296 ):

  • regctl blob get- file to fetch a file from a layer regctl blob get- get-file 从层中获取文件
  • regctl image get-file to fetch a file from the image layers regctl image get-file从图像层获取文件

Example:例子:

$ regctl image manifest busybox
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 1493,
    "digest": "sha256:6858809bf669cc5da7cb6af83d0fae838284d12e1be0182f92f6bd96559873e3"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 764618,
      "digest": "sha256:df8698476c65c2ee7ca0e9dbc2b1c8b1c91bce555819a9aaab724ac64241ba67"
    }
  ]
}

$ regctl blob get busybox sha256:6858809bf669cc5da7cb6af83d0fae838284d12e1be0182f92f6bd96559873e3 | jq .
{
  "architecture": "amd64",
  "config": {
    "Hostname": "",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    ...

Docker is not capable of saving layers individually, however there is a tool on Github called dlgrab that claims to do it. Docker无法单独保存图层,但Github上有一个名为dlgrab的工具声称可以执行此操作。 https://github.com/aidanhs/dlgrab https://github.com/aidanhs/dlgrab

While not capable of extracting a specific layer, the docker-save-last-layer command line utility is made to extract the last layer only. 虽然无法提取特定图层,但仍使用docker-save-last-layer命令行实用程序来提取最后一层。 Combined with docker build --squash you can avoid exporting the base layers. 结合docker build --squash您可以避免导出基础层。 This may help to accomplish your goals. 这可能有助于实现您的目标。

It works by using a patched version of the docker daemon inside a docker image that can access the images on your host machine. 它的工作原理是在docker镜像中使用docker守护程序的修补版本,该版本可以访问主机上的图像。 So it doesn't require doing a full docker save before using it. 因此,在使用之前不需要完整的docker save This makes it performant for large base images. 这使其适用于大型基础图像。

Typical usage is simple and looks like: 典型用法很简单,看起来像:

pip install d-save-last

docker build --t myimage --squash .
d-save-last myimage -o ./myimage.tar

For docker images that contain one layer.tar, this works.对于包含一个 layer.tar 的 docker 图像,此方法有效。

docker save myimage:latest | tar xO --wildcards '*.tar'  | tar xv myfile

First step extracts myimage as tar to stdout.第一步将 myimage 提取为 tar 到标准输出。 In the second step the '*.tar', which is in a dockerfile is usually layer.tar is selected and untared to stdout.在第二步中,位于 dockerfile 中的“*.tar”通常是 layer.tar 被选择并解压到标准输出。 In the third step we get the layer.tar from stdout and untar whatever file we want to pick在第三步中,我们从标准输出中获取 layer.tar 并解压缩我们想要选择的任何文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM