docker: extracting a layer from a image

前端 未结 5 1478
既然无缘
既然无缘 2020-12-28 20:11

Let\'s take the whalesay images as an example. docker history shows the following:

IMAGE               CREATED             CREATED BY                    


        
相关标签:
5条回答
  • 2020-12-28 20:53

    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.

    0 讨论(0)
  • 2020-12-28 20:53

    While not capable of extracting a specific layer, the docker-save-last-layer command line utility is made to extract the last layer only. Combined with docker build --squash you can avoid exporting the base layers. 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. So it doesn't require doing a full docker save before using it. 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
    
    0 讨论(0)
  • 2020-12-28 21:00

    In this specific case, it looks like the ADD command added the base image to the file system. If you run docker history --no-trunc docker/whalesay, the full command is:

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

    docker history reports that particular layer is 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. 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
    
    0 讨论(0)
  • 2020-12-28 21:05

    Docker is not capable of saving layers individually, however there is a tool on Github called dlgrab that claims to do it. https://github.com/aidanhs/dlgrab

    0 讨论(0)
  • 2020-12-28 21:15

    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 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. Inspecting this tarball shows, in my case, a file repositories with

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

    which indicates, that the latest layer is fdf43.... You can get a tarball with the file system contents of this layer via

    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.

    0 讨论(0)
提交回复
热议问题