Docker
Docker Compose
File Transfer
Container Management
DevOps

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.

dockerfile
1FROM python:3.12-slim
2WORKDIR /app
3COPY requirements.txt .
4RUN pip install -r requirements.txt
5COPY . .
6CMD ["python", "app.py"]

Then Compose points to that build.

yaml
1services:
2  web:
3    build: .
4    ports:
5      - "8000:8000"

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.

yaml
1services:
2  web:
3    image: python:3.12-slim
4    working_dir: /app
5    command: python app.py
6    volumes:
7      - ./src:/app

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.

bash
docker compose ps

Find the container name, then copy the file.

bash
docker cp ./local-config.json myproject-web-1:/app/config.json

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 COPY in the Dockerfile for application files that belong in the image
  • use Compose volumes for live development files or shared host data
  • use docker cp for 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.

yaml
1services:
2  app:
3    image: my-image
4    volumes:
5      - appdata:/data
6
7volumes:
8  appdata:

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 COPY in the Dockerfile when the files belong in the image.
  • Use Compose bind mounts when the container should see live host files.
  • Use docker cp only 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.

Course illustration
Course illustration

All Rights Reserved.