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?
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).
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.
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.
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.
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
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With