As more of our applications are deployed to cloud environments, working with Docker is becoming a necessary skill for developers. Often when debugging applications, it is useful to copy files into or out of our Docker containers.
In this tutorial, we'll look at some different ways we can copy files to and from Docker containers.
2. Docker cp Command
The quickest way to copy files to and from a Docker container is to use the docker cp command. This command closely mimics the Unix cp command and has the following syntax:
docker cp <SRC> <DEST>
Before we look at some examples of this command, let's assume we have the following Docker containers running:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1477326feb62 grafana/grafana "/run.sh" 2 months ago Up 3 days 0.0.0.0:3000->3000/tcp grafana 8c45029d15e8 prom/prometheus "/bin/prometheus --c…" 2 months ago Up 3 days 0.0.0.0:9090->9090/tcp prometheus
The first example copies a file from the /tmp directory on the host machine into the Grafana install directory in the grafana container:
docker cp /tmp/config.ini grafana:/usr/share/grafana/conf/
We can also use container IDs instead of their names:
docker cp /tmp/config.ini 1477326feb62:/usr/share/grafana/conf/
To copy files from the grafana container to the /tmp directory on the host machine, we just switch the order of the parameters:
docker cp grafana:/usr/share/grafana/conf/defaults.ini /tmp
We can also copy an entire directory instead of single files. This example copies the entire conf directory from the grafana container to the /tmp directory on the host machine:
docker cp grafana:/usr/share/grafana/conf /tmp
The docker cp command does have some limitations. First, we cannot use it to copy between two containers. It can only be used to copy files between the host system and a single container.
Second, while it does have the same syntax as the Unix cp command, it does not support the same flags. In fact, it only supports two:
-a: Archive mode, which preserves all uid/gid information of the files being copied
-L: Always follow symbolic links in SRC
3. Volume Mounts
Another way to copy files to and from Docker containers is to use a volume mount. This means we make a directory from the host system available inside the container.
To use volume mounts, we have to run our container with the -v flag:
docker run -d --name=grafana -p 3000:3000 grafana/grafana -v /tmp:/transfer
The command above runs a grafana container and mounts the /tmp directory from the host machine as a new directory inside the container named /transfer. If we wanted to, we could provide multiple -v flags to create multiple volume mounts inside the container.
There are several advantages to this approach. First, we can use the Unix cp command, which has many more flags and options over the docker cp command.
The second advantage is that we can create a single shared directory for all Docker containers. This means we can copy directly between containers as long as they all have the same volume mount.
Keep in mind this approach has the disadvantage that all files have to go through the volume mount. This means we cannot copy files in a single command. Instead, we first copy files into the mounted directory, and then into their final desired location.
Another drawback to this approach is we may have issues with file ownership. Docker containers typically only have a root user, which means files created inside the container will have root ownership by default. We can use the Unix chown command to restore file ownership if needed on the host machine.
Dockerfiles are used to build Docker images, which are then instantiated into Docker containers. Dockerfiles can contain several different instructions, one of which is COPY.
The COPY instruction lets us copy a file (or files) from the host system into the image. This means the files become a part of every container that is created from that image.
The syntax for the COPY instruction is similar to other copy commands we saw above:
COPY <SRC> <DEST>
Just like the other copy commands, SRC can be either a single file or a directory on the host machine. It can also include wildcard characters to match multiple files.
Let's look at some examples.
This will copy a single from the current Docker build context into the image:
COPY properties.ini /config/
And this will copy all XML files into the Docker image:
COPY *.xml /config/
The main downside of this approach is that we cannot use it for running Docker containers. Docker images are not Docker containers, so this approach only makes sense to use when the set of files needed inside the image is known ahead of time.
In this tutorial, we've seen how to copy files to and from a Docker container. Each has some pros and cons, so we must pick the approach that best suits our needs.