Saving docker container image contents to local directory

You can use commands like docker save to export a container to a directory or tar archive, but the problem is that this saves the individual image layers, while what we typically want is to save files that are seen in the final, merged filesystem image.

You can use docker cp to copy files from a running or stopped container, but you cannot use this to copy directly from an image.

The best way to achieve this I’ve found is to use docker build with the --output flag.

$ printf "FROM %s\n" busybox:latest > Dockerfile
$ docker build --output type=local,dest=output_dir .
[+] Building 0.3s (5/5) FINISHED                docker:default
 => [internal] load .dockerignore                         0.0s
 => => transferring context: 2B                           0.0s
 => [internal] load build definition from Dockerfile      0.0s
 => => transferring dockerfile: 115B                      0.0s
 => [internal] load metadata for docker.io/library/busyb  0.0s
 => [1/1] FROM docker.io/library/busybox:latest           0.0s
 => exporting to client directory                         0.0s
 => => copying files 1.28MB                               0.0s

$ ls -l output_dir
drwxr-xr-x@ - work work 25 May  2022 bin
drwxr-xr-x@ - work work 25 May  2022 dev
drwxr-xr-x@ - work work 25 May  2022 etc
drwxr-xr-x@ - work work 25 May  2022 home
drwx------@ - work work 25 May  2022 root
drwxrwxrwt@ - work work 25 May  2022 tmp
drwxr-xr-x@ - work work 25 May  2022 usr
drwxr-xr-x@ - work work 25 May  2022 var

Note that this relies on docker BuildKit and also works precisely the same way when using podman build or buildah build.