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:
-
Debugging and Troubleshooting:
- Extract log files from a crashed container
- Copy configuration files to inspect settings
- Retrieve core dumps or error reports
-
Quick Fixes:
- Hot-patch a configuration file without rebuilding
- Update a static asset in a running container
- Apply emergency fixes in production
-
Data Extraction:
- Export database backups from containers
- Retrieve generated reports or files
- Extract build artifacts from build containers
-
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 .
Issue 4: Copying Symlinks
# 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.