Copying files to a container with Docker Compose
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When people say they want to copy files into a container with Docker Compose, they usually mean one of three different things: bake files into the image at build time, mount files from the host at runtime, or push files into an already running container for a one-off task. The right approach depends on whether the files are part of the application, part of local development, or just temporary operational data.
Build-Time Copying With COPY
If the files are part of the image itself, the correct place to copy them is the Dockerfile, not the Compose file.
Then Compose points to that build.
This is the right answer when the container should always contain those files, including in CI, test, and production environments.
Runtime Copying With Bind Mounts
If you want the container to see files from your local machine without rebuilding the image every time, use a bind mount.
With that configuration, changes in ./src on the host appear immediately at /app inside the container.
This is the most common development-time solution. It is not really "copying" in the image sense. It is mounting a host path into the container namespace.
One-Off Copying to a Running Container
Sometimes you already have a running Compose-managed container and need to send in a file once. That is operationally different from image design or a bind mount.
In that case, use the Docker CLI against the actual container.
Find the container name, then copy the file.
This works, but it should usually be treated as a temporary manual action. If the file is required every time the container starts, encode that requirement in the image or Compose configuration instead of relying on ad hoc copying.
Choose the Right Method for the Real Requirement
A useful rule is:
- use
COPYin theDockerfilefor application files that belong in the image - use Compose
volumesfor live development files or shared host data - use
docker cpfor one-off operational changes to an existing container
That distinction keeps your container workflow reproducible. A surprising number of Docker problems come from using a temporary technique where a declarative technique should have been used.
Beware of Rebuild and Mount Interactions
One common source of confusion is building files into an image and then hiding them with a bind mount at runtime.
For example, suppose your image contains /app because the Dockerfile copied it there. If your Compose file later mounts ./src:/app, the mounted directory replaces what you would otherwise see from the image at that path.
That behavior is correct, but it surprises people who think their build-time copy "did not work." The copy worked. The runtime mount just took precedence in the container view.
Named Volumes Are Different Again
A named volume is not the same as copying from the host and not the same as baking files into an image.
Named volumes are mainly for persisted container-managed data. They are useful for databases, uploads, or caches, not for routinely pushing source files from your laptop into a service.
Common Pitfalls
The most common mistake is trying to express one-off file copying directly in Compose as if Compose were a deployment-time file transfer tool. It is better at defining services, builds, networks, and mounts.
Another mistake is using docker cp for files that should have been part of the image or a bind mount. That creates drift between containers.
A third issue is forgetting that a bind mount can hide files baked into the image at the same path.
Finally, do not treat manual container changes as permanent. Containers are replaceable, so persistent behavior must come from the image or configuration.
Summary
- Use
COPYin theDockerfilewhen the files belong in the image. - Use Compose bind mounts when the container should see live host files.
- Use
docker cponly for one-off copying into an existing running container. - Expect bind mounts to override what the image already contains at the same path.
- Use named volumes for persisted container data, not as a substitute for image content.
- Pick the method that matches whether the need is build-time, runtime, or temporary operations.

