Introduction

While volumes and bind mounts are the primary methods for persistent data in Docker, there are times when you need to quickly copy files between your host machine and a running or stopped container. This is where the docker cp command becomes invaluable.

This comprehensive guide covers everything about transferring content with Docker, from basic file copying to advanced data management strategies, troubleshooting, and best practices.

Why You Need docker cp

Common Use Cases:

  1. Debugging and Troubleshooting:

    • Extract log files from a crashed container
    • Copy configuration files to inspect settings
    • Retrieve core dumps or error reports
  2. Quick Fixes:

    • Hot-patch a configuration file without rebuilding
    • Update a static asset in a running container
    • Apply emergency fixes in production
  3. Data Extraction:

    • Export database backups from containers
    • Retrieve generated reports or files
    • Extract build artifacts from build containers
  4. Development Workflows:

    • Copy compiled binaries from build containers
    • Extract test results and coverage reports
    • Retrieve generated documentation

When NOT to Use docker cp:

  • For persistent application data → Use volumes
  • For development with live-reload → Use bind mounts
  • For sharing data between containers → Use volumes or networks

Part 1: Understanding docker cp

The Basics

The docker cp command copies files/folders between a container and the local filesystem. It works with both running and stopped containers.

Syntax:

# Copy FROM container TO host
docker cp <container>:<src_path> <dest_path>

# Copy FROM host TO container
docker cp <src_path> <container>:<dest_path>

Key Characteristics:

  • Works with running AND stopped containers
  • Preserves file permissions and ownership
  • Can copy files or entire directories
  • Does not require the container to be running
  • Creates a snapshot copy (not a live sync)

Part 2: Basic File Transfer Operations

Copying Files from Container to Host

Single File:

# Copy a log file from container to current directory
docker cp my-container:/var/log/app.log .

# Copy to a specific location
docker cp my-container:/etc/nginx/nginx.conf /tmp/nginx-backup.conf

Directory:

# Copy entire directory
docker cp my-container:/app/logs ./container-logs

# Copy directory contents (note the trailing /.)
docker cp my-container:/app/logs/. ./container-logs

Example: Extract Database Backup

# Create backup inside container
docker exec my-postgres pg_dump -U postgres mydb > /tmp/backup.sql

# Copy backup to host
docker cp my-postgres:/tmp/backup.sql ./backups/mydb-$(date +%Y%m%d).sql

Copying Files from Host to Container

Single File:

# Copy configuration file into container
docker cp ./config.json my-container:/app/config.json

# Copy with different name
docker cp ./local-settings.json my-container:/app/settings.json

Directory:

# Copy entire directory
docker cp ./static-assets my-container:/var/www/html/

# Copy directory contents
docker cp ./static-assets/. my-container:/var/www/html/assets/

Example: Hot-Patch a Configuration

# Edit config locally
vim nginx.conf

# Copy to container
docker cp nginx.conf my-nginx:/etc/nginx/nginx.conf

# Reload nginx
docker exec my-nginx nginx -s reload

Part 3: Advanced Techniques

Working with Stopped Containers

One of docker cp’s superpowers is working with stopped containers:

# Container crashes
docker ps -a
# CONTAINER ID   STATUS
# abc123         Exited (1) 2 minutes ago

# Still can extract logs!
docker cp abc123:/var/log/app.log ./crash-logs/

# Extract core dump
docker cp abc123:/tmp/core ./debugging/

Copying from Specific Container Layers

You can reference containers by ID or name:

# By name
docker cp my-app:/app/data.json .

# By container ID
docker cp abc123def:/app/data.json .

# By short ID
docker cp abc:/app/data.json .

Using docker cp in Scripts

Backup Script Example:

#!/bin/bash
# backup-container-data.sh

CONTAINER_NAME="my-database"
BACKUP_DIR="./backups/$(date +%Y%m%d)"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Create backup inside container
docker exec $CONTAINER_NAME /backup-script.sh

# Copy backup to host
docker cp $CONTAINER_NAME:/tmp/backup.tar.gz \
  "$BACKUP_DIR/backup-$TIMESTAMP.tar.gz"

# Cleanup container
docker exec $CONTAINER_NAME rm /tmp/backup.tar.gz

echo "Backup completed: $BACKUP_DIR/backup-$TIMESTAMP.tar.gz"

Copying with Tar Streams

For large directories, you can use tar to stream data:

From container to host:

docker exec my-container tar czf - /app/data | tar xzf - -C ./local-data

From host to container:

tar czf - ./local-data | docker exec -i my-container tar xzf - -C /app/

This is more efficient for large datasets as it streams the data.

Part 4: Practical Examples

Example 1: Extracting Build Artifacts

# Build stage in multi-stage Dockerfile
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Instead of copying to final stage, extract to host
docker build --target builder -t my-app-builder .
docker create --name extract my-app-builder
docker cp extract:/app/dist ./dist
docker rm extract

Example 2: Debugging Production Issues

# Production container is misbehaving
CONTAINER_ID=$(docker ps -q -f name=prod-app)

# Extract logs
docker cp $CONTAINER_ID:/var/log/app ./debug-logs/

# Extract current config
docker cp $CONTAINER_ID:/etc/app/config.yaml ./debug-config/

# Extract heap dump (Java app)
docker exec $CONTAINER_ID jmap -dump:live,format=b,file=/tmp/heap.bin 1
docker cp $CONTAINER_ID:/tmp/heap.bin ./heap-dumps/

Example 3: Database Migration

# Export from old container
docker exec old-db mysqldump -u root -p mydb > /tmp/export.sql
docker cp old-db:/tmp/export.sql ./migration/

# Import to new container
docker cp ./migration/export.sql new-db:/tmp/
docker exec new-db mysql -u root -p mydb < /tmp/export.sql

Example 4: Updating SSL Certificates

# New certificates obtained
ls certs/
# fullchain.pem  privkey.pem

# Copy to nginx container
docker cp certs/fullchain.pem my-nginx:/etc/nginx/ssl/
docker cp certs/privkey.pem my-nginx:/etc/nginx/ssl/

# Reload nginx
docker exec my-nginx nginx -s reload

Part 5: Permissions and Ownership

Understanding Permission Preservation

docker cp preserves the original file permissions and ownership:

# On host (as user 1000)
touch myfile.txt
ls -l myfile.txt
# -rw-r--r-- 1 user user 0 Jan 14 10:00 myfile.txt

# Copy to container
docker cp myfile.txt my-container:/app/

# Check in container
docker exec my-container ls -l /app/myfile.txt
# -rw-r--r-- 1 1000 1000 0 Jan 14 10:00 /app/myfile.txt

Changing Ownership After Copy

# Copy file
docker cp config.json my-container:/app/

# Change ownership to app user
docker exec my-container chown appuser:appgroup /app/config.json

Copying as Root

If you need specific permissions:

# Copy and set ownership in one go
docker cp myfile.txt my-container:/tmp/ && \
docker exec my-container sh -c 'chown root:root /tmp/myfile.txt && mv /tmp/myfile.txt /app/'

Part 6: Troubleshooting Common Issues

Issue 1: “No such container”

docker cp my-container:/app/file.txt .
# Error: No such container: my-container

# Solution: Check container name/ID
docker ps -a | grep my-container

# Use correct name or ID
docker cp actual-container-name:/app/file.txt .

Issue 2: “No such file or directory”

docker cp my-container:/wrong/path/file.txt .
# Error: No such file or directory

# Solution: Verify path exists
docker exec my-container ls -la /app/
docker cp my-container:/app/file.txt .

Issue 3: Permission Denied

docker cp my-container:/root/secret.txt .
# Error: Permission denied

# Solution: Copy to /tmp first, then extract
docker exec my-container cp /root/secret.txt /tmp/
docker cp my-container:/tmp/secret.txt .
# Symlinks are followed by default
docker cp my-container:/app/link.txt .
# Copies the target file, not the link

# To preserve symlinks, use tar
docker exec my-container tar cf - /app/link.txt | tar xf -

Part 7: Best Practices

1. Use Volumes for Persistent Data

Don’t:

# Copying database files manually
docker cp my-db:/var/lib/mysql ./backup

Do:

# Use volumes for databases
docker run -v db-data:/var/lib/mysql mysql

2. Automate with Scripts

Create reusable backup scripts:

#!/bin/bash
# container-backup.sh
CONTAINER=$1
BACKUP_PATH=$2
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

docker cp $CONTAINER:$BACKUP_PATH ./backups/$CONTAINER-$TIMESTAMP/

3. Verify Copies

# Copy file
docker cp large-file.tar.gz my-container:/app/

# Verify with checksum
md5sum large-file.tar.gz
docker exec my-container md5sum /app/large-file.tar.gz

4. Clean Up After Copying

# Copy file
docker cp my-container:/tmp/large-export.tar.gz .

# Clean up in container
docker exec my-container rm /tmp/large-export.tar.gz

5. Use Appropriate Methods

Scenario Best Method
Persistent application data Volumes
Development with live-reload Bind mounts
One-time file extraction docker cp
Configuration hot-patch docker cp
Debugging/log extraction docker cp
Build artifacts docker cp or multi-stage builds

Part 8: Integration with CI/CD

GitLab CI Example

# .gitlab-ci.yml
build:
  stage: build
  script:
    - docker build -t my-app:$CI_COMMIT_SHA .
    - docker create --name extract my-app:$CI_COMMIT_SHA
    - docker cp extract:/app/dist ./dist
    - docker rm extract
  artifacts:
    paths:
      - dist/

Jenkins Pipeline Example

pipeline {
    agent any
    stages {
        stage('Extract Artifacts') {
            steps {
                script {
                    sh '''
                        docker create --name extract my-app:latest
                        docker cp extract:/app/build ./artifacts
                        docker rm extract
                    '''
                }
                archiveArtifacts artifacts: 'artifacts/**'
            }
        }
    }
}

Conclusion

The docker cp command is a powerful tool for transferring files between containers and hosts. This guide covered:

  • Understanding when to use docker cp vs volumes/bind mounts
  • Basic file and directory copying operations
  • Advanced techniques (tar streams, stopped containers)
  • Practical examples (backups, debugging, migrations)
  • Permission handling and troubleshooting
  • Best practices and CI/CD integration

Key Takeaways:

  • Use docker cp for one-time transfers and debugging
  • Use volumes for persistent application data
  • Use bind mounts for development workflows
  • Always verify large file transfers
  • Clean up temporary files after copying
  • Automate repetitive copy operations with scripts

With docker cp in your toolkit, you have the flexibility to move data in and out of containers whenever needed, making debugging, backups, and emergency fixes much easier.