When starting a Docker container, this uses a so-called "Docker Image" in the background. These images can be built on top of each other (called layers). An image can be created from yet another image, resulting in many layers.
The contents of a Docker image usually come from a code repository, such as GitHub. However sometimes you don't have access to the code source and need to look at the contents differently. Luckily the contents of a Docker image can be extracted.
docker save (somewhat helpful)
The docker save command can be used to extract an image into a bundled package:
ck@mint ~ $ docker save nginx:latest > /tmp/nginx.tar
ck@mint ~ $ mkdir /tmp/nginx; tar -xf /tmp/nginx.tar -C /tmp/nginx
After unpacking the created tar file, the target directory shows some files, including a "blobs" directory.
ck@mint ~ $ ls -la /tmp/nginx
total 44
drwxrwxr-x 3 ck ck 4096 Mar 27 07:20 ./
drwxrwxrwt 22 root root 20480 Mar 27 07:20 ../
drwxr-xr-x 3 ck ck 4096 Feb 9 2023 blobs/
-rw-r--r-- 1 ck ck 362 Mar 27 07:18 index.json
-rw-r--r-- 1 ck ck 1981 Jan 1 1970 manifest.json
-rw-r--r-- 1 ck ck 31 Jan 1 1970 oci-layout
-rw-r--r-- 1 ck ck 88 Jan 1 1970 repositories
These blobs are the previously mentioned layers – which again is a file.
ck@mint ~ $ ls -la /tmp/nginx/blobs/sha256/
total 142864
drwxr-xr-x 2 ck ck 4096 Mar 27 07:18 ./
drwxr-xr-x 3 ck ck 4096 Feb 9 2023 ../
-rw-r--r-- 1 ck ck 1686 Feb 9 2023 18f12028ebb36ad53f82ea2cd0cab88781e369ff26801ddf892a54feaa51f480
-rw-r--r-- 1 ck ck 3584 Feb 9 2023 21a95e83c568f2d9b955c4c6462d87836333eb352c2d7c2273c5887fa703dfdc
-rw-r--r-- 1 ck ck 1156 Jan 1 1970 220523042b6000904ccbfad17bde6d5d74ddda68884a6f74a87e8a3d32993bd4
-rw-r--r-- 1 ck ck 4608 Feb 9 2023 2df186f5be5ceb2fa3ee025010e8f7e4e9bb2eda2ed7f8711d7e657520939b5d
-rw-r--r-- 1 ck ck 7168 Feb 9 2023 3ea1bc01cbfeba5aa6422854e871bc492fee172f196e332317522e991452c757
-rw-r--r-- 1 ck ck 7655 Feb 9 2023 3f8a00f137a0d2c8a2163a09901e28e2471999fde4efc2f9570b91f1c30acf94
-rw-r--r-- 1 ck ck 84000256 Feb 9 2023 4695cdfb426a05673a100e69d2fe9810d9ab2b3dd88ead97c6a3627246d83815
-rw-r--r-- 1 ck ck 406 Feb 9 2023 6371414131944e834e61fc30130e37c1c5eb6cf57b23e8a20f80e2e92a753fe5
-rw-r--r-- 1 ck ck 482 Feb 9 2023 680edc51719806da8cfbd1847403f6e36327a07c3103d9be9390783c0baae531
-rw-r--r-- 1 ck ck 62213632 Feb 9 2023 81e05d8cedf626d8f5379172691805c1956449f3ab1bc2def9d67bc6ca0e5e89
-rw-r--r-- 1 ck ck 3584 Feb 9 2023 a76121a5b9fdeef2d04457a2898cd5889c19672c2ad7fc66cc25d2bf6a8db7a5
-rw-r--r-- 1 ck ck 482 Feb 9 2023 bfb3462f8d4ff568d4b836201ae205d1b8bebff2311059a13f678363ed56e7bb
-rw-r--r-- 1 ck ck 482 Feb 9 2023 d52c3a1351077f1b3368791116e09eff483bcb5fb9027510ad7917bf78e065cf
-rw-r--r-- 1 ck ck 482 Feb 9 2023 df18efa9d2c48b2e1d5b8e119343f0d30dd145bafba79df143f7b1a6ed972570
Now you could do the same unpack steps using tar for each of these layer files, for example with a for loop.
However there's an easier way.
docker-image-extract is an excellent helper script
Obviously you're not the first person trying to extract files from a Docker image. Jeremy Lin's "docker-image-extract" script is a great helper script which does these manual tasks and steps (download of the image and tar unpacking) automatically and saves the resulting files and directories into an output directory.
Clone the public repository to your local machine:
ck@mint ~/Git $ git clone https://github.com/jjlin/docker-image-extract.git
ck@mint ~/Git $ cd docker-image-extract
Then run the Shell script in the following format: ./docker-image-extract [options] image
For example if you want to save the output of the image into a specific directory (/tmp/nginx-image here):
ck@mint ~/Git/docker-image-extract $ ./docker-image-extract -o /tmp/nginx-image nginx:latest
Getting multi-arch manifest list...
Platform linux/amd64 resolved to 'sha256:54809b2f36d0ff38e8e5362b0239779e4b75c2f19ad70ef047ed050f01506bb4'...
Getting API token...
Getting image manifest for library/nginx:latest...
Fetching and extracting layer 6e909acdb790c5a1989d9cfc795fda5a246ad6664bb27b5c688e2b734b2c5fad...
Fetching and extracting layer 5eaa34f5b9c2a13ef2217ceb966953dfd5c3a21a990767da307be1f57e5a1e4f...
Fetching and extracting layer 417c4bccf5349be7cd4ba91b1a2077ecf0ab50b3831bb071ba31f2c8bac02ed1...
Fetching and extracting layer e7e0ca015e553ccff5686ec2153c895313675686d3f6940144ce935c07554d85...
Fetching and extracting layer 373fe654e9845b69587105e1b82833209521db456bdc5bc26ac7260e3eb2dd52...
Fetching and extracting layer 97f5c0f51d43d499970597eef919f9170954289eff0c5d7b8f8afd73dbb57977...
Fetching and extracting layer c22eb46e871ad1cda19691450312c6b5c25eb5e6836773821d8091cffb6327cc...
Image contents extracted into /tmp/nginx-image.
The full contents of this Docker image – including all layers – can now be seen in the output directory:
ck@mint ~ $ ls -la /tmp/nginx-image/
total 92
drwxr-xr-x 18 ckadm ckadm 4096 Mar 27 07:36 .
drwxrwxrwt 24 root root 20480 Mar 27 07:36 ..
lrwxrwxrwx 1 ckadm ckadm 7 Mar 17 01:00 bin -> usr/bin
drwxr-xr-x 2 ckadm ckadm 4096 Mar 7 18:30 boot
drwxr-xr-x 2 ckadm ckadm 4096 Mar 17 01:00 dev
drwxr-xr-x 2 ckadm ckadm 4096 Mar 18 00:12 docker-entrypoint.d
-rwxr-xr-x 1 ckadm ckadm 1620 Mar 18 00:12 docker-entrypoint.sh
drwxr-xr-x 34 ckadm ckadm 4096 Mar 18 00:12 etc
drwxr-xr-x 2 ckadm ckadm 4096 Mar 7 18:30 home
lrwxrwxrwx 1 ckadm ckadm 7 Mar 17 01:00 lib -> usr/lib
lrwxrwxrwx 1 ckadm ckadm 9 Mar 17 01:00 lib64 -> usr/lib64
drwxr-xr-x 2 ckadm ckadm 4096 Mar 17 01:00 media
drwxr-xr-x 2 ckadm ckadm 4096 Mar 17 01:00 mnt
drwxr-xr-x 2 ckadm ckadm 4096 Mar 17 01:00 opt
drwxr-xr-x 2 ckadm ckadm 4096 Mar 7 18:30 proc
drwx------ 2 ckadm ckadm 4096 Mar 17 01:00 root
drwxr-xr-x 3 ckadm ckadm 4096 Mar 17 01:00 run
lrwxrwxrwx 1 ckadm ckadm 8 Mar 17 01:00 sbin -> usr/sbin
drwxr-xr-x 2 ckadm ckadm 4096 Mar 17 01:00 srv
drwxr-xr-x 2 ckadm ckadm 4096 Mar 7 18:30 sys
drwxrwxr-x 2 ckadm ckadm 4096 Mar 17 01:00 tmp
drwxr-xr-x 12 ckadm ckadm 4096 Mar 17 01:00 usr
drwxr-xr-x 11 ckadm ckadm 4096 Mar 17 01:00 var