Extracting files from Docker Images and Containers

Yash Soni

Yash Soni / December 12, 2022

3 min read

Docker is a powerful tool for running and managing containers, which are lightweight and portable packages that contain all the necessary files and dependencies for an application to run.

One useful feature of Docker is the ability to extract the contents of a container image, which can be useful for debugging or for making backups.

There are a few ways to achive this. We will begin with a very simple Dockerfile which creates a build-logs.txt file during the build process.

Dockerfile
FROM alpine as BUILD
WORKDIR /home
RUN echo "Hello Docker" > build-logs.txt

1. Export entire contents of container to a tar file

bash
docker build -t buildx-cp .

# create a container named "tmp" without running it
docker create --name tmp buildx-cp

# export the contents of entire image to a tar file
docker export tmp > myimage.tar

# remove the created container
docker rm tmp

2. Export a single file from the container to filesystem

When we need a specific file from the running container, we can use the cp command to copy contents from the container to the filesystem (or vice-versa).

bash
# copy the file from a container to filesystem
docker cp tmp:/home/build-logs.txt .

# copy myFile from filesystem to the container
docker cp ./myfile tmp:/home

3. Export files from multi-staged builds

Docker multi-staged builds are a way to optimize the Docker build process by using multiple build stages in a single Dockerfile. This allows you to separate your build process into multiple stages, each with its own specific purpose, and only include the necessary files and dependencies in the final Docker image. This can result in smaller, more efficient Docker images that are easier to manage and deploy.

Dockerfile
FROM alpine as BUILD

WORKDIR /home
ADD ./isPrime.sh .
RUN chmod +x ./isPrime.sh
RUN echo "Hello Docker" >build-logs.txt

FROM alpine as FINAL
WORKDIR /home
COPY --from=BUILD /home/isPrime.sh .
CMD ["sh", "isPrime.sh"]

Here we create a FINAL image copying only required files from the BUILD stage.

Let's say we need to get the contents of the build-logs.txt file which is generated as a part of the build process. With the solutions mentioned till now, we will have to unnecessarily copy this file in FINAL layer to be able to copy the contents.

A better way is to use Docker Exporters which provides handy options to output the entire Docker image to disk as a directory or TAR ball alongwith a --target option.

However, instead of copying the entire contents, we can use the minimilist scratch image to copy only the required files in an intermediate stage.

Dockerfile
FROM alpine as BUILD

WORKDIR /home
ADD ./isPrime.sh .
RUN chmod +x ./isPrime.sh
RUN echo "Hello Docker" >build-logs.txt

# take an "empty" image as a starting point & copy the requires artefacts
FROM scratch as EXPORT
COPY --from=BUILD /home/build-logs.txt ./

FROM alpine as FINAL
WORKDIR /home
COPY --from=BUILD /home/isPrime.sh .
CMD ["sh", "isPrime.sh"]

Now we can "target" the docker build till the EXPORT stage and gather the output using the output argument.

bash
docker build --target EXPORT --output type=local,dest=out .

ls out/
build-logs.txt

Using this method, we can extract files generated in intermediatery stages without copying to subsequent stages!