How to Use Docker Cp to Copy Files Between Host and Containers

October 2024 ยท 5 minute read

Quick Links

Need to get some files into or out of a Docker container? The docker cp command lets you copy between host and container filesystems so you can add config details, create backups, and restore existing data.

Basic Syntax

docker cp accepts source and destination paths as its two arguments:

docker cp example.txt my-container:/example.txt

Here example.txt is being copied from your working directory to /example.txt in the my-container container. You could reverse the two arguments to copy /example.txt out of the container and into your working directory.

The argument referencing the container path needs to be prefixed with a container ID or name followed by a colon (:). You can find the ID or name of a running container with docker ps.

Each docker cp command needs one local filesystem path and one container path - you can't directly copy between two containers. Use a multi-step procedure if you need to do this, copying first from the source container to your filesystem, then from the new local path into the target container.

Copying Entire Directories

docker cp can recursively copy directories too:

docker cp /home/demo/website apache-container:/var/www/html/.

Docker will copy everything in /home/demo/website and transfer it into /var/www/html.

Copy Behavior

When you're copying a file, Docker creates a new file at the destination if it doesn't already exist. Existing files are overwritten with the new content. When the destination's a directory, the file gets copied into it using the source filename. An exception is when the specified destination ends with a /, denoting a directory, but the path does not already exist. In this scenario an error will be raised.

The process is a little more complicated for directory copies. A new directory will be created at the destination with the contents of the source directory, if the destination path doesn't already exist. When it does exist, the behavior differs depending on whether you've included a trailing /. component in the path.

The subtle distinction dictates whether a new subdirectory is created inside the destination.

Command Limitations

Despite its name, docker cp is not a complete implementation of the cp shell command. The cp flags are not supported, except for -a and -L:

For more advanced use cases where selective copying is required, you'll need to fallback to using a different approach.

Using Bind Mounts to Copy Files

Docker volumes provide another way of moving files between containers and your host. Bind mounting a local directory into a container lets you access its contents from your host filesystem, removing the need to use docker cp.

docker run -v /example/host/directory:/container/path my-image:latest

The contents of the /example/host/directory path are mounted into the container's filesystem at /container/path. You can interact with these files outside of Docker using familiar tools such as cp, rsync, and your graphical file browser.

This technique is only useful when you're working with a single container directory. It doesn't work well when you're copying from arbitrary locations as you need to know the paths you'll be using ahead of time, when the container is created.

You should also be wary of filesystem permissions: files created within the container will usually be owned by root. This can create awkward scenarios on the host where you're unable to edit or delete files inside the bound directory. Use the chown command on the host and inside the container to switch the ownership depending on environment if necessary.

What About COPY in Dockerfiles?

docker cp can sometimes be confused with the COPY instruction in Dockerfiles. It's important to recognize that these two features serve very different use cases.

COPY can't be used to move files between your host and a running container. It's for getting files into images during the build process:

COPY /home/me/my-website /var/www/html/.

Here website source code gets copied into an image as part of a build. This is a one-time process. Every container started from the image would include the website source as it was at the time you ran docker build.

docker cp lets you replace that source code with a newer version once a container is running. COPY instructions are for making files part of a static image; cp commands interact with live containers.

When to Copy Files With Docker?

Manually copying files from your host to a Docker container, or vice versa, should be a relatively rare occurrence. Images are meant to be self-sufficient so they should come with everything you need to start an instance. Configuration is usually handled via environment variables.

Containers which need to store data persistently should be using Docker volumes. Volumes allow data to outlive any single container so you don't need to manually docker cp before replacing an instance. When you're making backups, copy the volumes from your host, instead of pulling files out of containers.

docker cp is most useful when debugging containers or working in a development environment. Sometimes you need to manually inject a temporary config file or pull out a buried log. Using docker cp is quicker and more convenient than rebuilding the entire image each time you make a code change.

Always remember that files copied into containers will only persist as long as the container lives. Starting another container from the same image will give you a clean slate, without the files you added with docker cp.

Summary

docker cp lets you move files between your host and your Docker containers. It works with files and directories but lacks most of the advanced functionality in the shell-based cp command.

Regular use of docker cp indicates a potential departure from container best practices. It's wise to treat it as a convenience tool for development use, rather than an integral part of working with containers. Long-term file persistence should be implemented with volumes as these are first-class components in the Docker ecosystem.

ncG1vNJzZmivp6x7qbvWraagnZWge6S7zGibnq6fpcBwtM6wZK2nXarApnnDqJqknaJisLF506hknKegrnqntcueqmaalanEprHNZp%2Boq6Rirq%2BwjJymp6yRnrumvtJo