Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker: extracting a layer from a image

Tags:

docker

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

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. Is there a tool/way for doing this?

like image 398
lang2 Avatar asked Nov 13 '16 15:11

lang2


People also ask

Can we extract files from docker image?

You can use the docker cp command to copy the file. The first path (Source) is the path in the Docker Container and the second one is the path inside your Local System (Destination).

Do docker images share layers?

Docker already has all the layers from the first image, so it does not need to pull them again. The two images share any layers they have in common.

Can code be extracted from docker image?

1. Using COPY or ADD command: You can use COPY or ADD command within Dockerfile to copy your file/code into the Docker container. The following Dockerfile example shows how to add the current working directory files and folders into the directory /usr/Qxf2_POM of the container image.

Does docker copy create a layer?

A Dockerfile adheres to a specific format and set of instructions which you can find at Dockerfile reference. Each instruction creates one layer: FROM creates a layer from the ubuntu:18.04 Docker image. COPY adds files from your Docker client's current directory.


4 Answers

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
like image 110
bonh Avatar answered Oct 04 '22 05:10

bonh


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.

like image 28
Michael Kopp Avatar answered Oct 04 '22 04:10

Michael Kopp


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.

like image 41
luanbuingoc Avatar answered Oct 04 '22 03:10

luanbuingoc


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
like image 40
brthornbury Avatar answered Oct 04 '22 05:10

brthornbury