What is the difference between the COPY and ADD commands in a Dockerfile, and when should I use one over the other?
COPY
The COPY instruction will copy new files from
ADD
The ADD instruction will copy new files from
COPY and ADD commands in Dockerfiles both copy files from the host to the container, but ADD has additional features like automatic extraction of compressed files and remote URL downloading, while COPY is simpler and more predictable. You should prefer COPY for straightforward file copying and use ADD only when you specifically need its extra functionality like extracting archives or downloading remote files.
Contents
- Basic Definitions
- Key Differences
- When to Use COPY
- When to Use ADD
- Best Practices
- Examples and Use Cases
- Performance Considerations
Basic Definitions
The COPY instruction is straightforward - it copies files or directories from the build context into the container’s filesystem. The syntax is simple: COPY <src> <dest> where <src> can be a file or directory path, and <dest> is the destination path in the container.
The ADD instruction appears similar on the surface - ADD <src> <dest> - but includes additional functionality beyond simple file copying. While both instructions ultimately place files into the container, ADD has special handling for certain file types and sources.
Key Differences
Automatic File Extraction
ADD can automatically extract compressed files like .tar, .tar.gz, .tar.bz2, .tar.xz, .zip, and .tgz when they’re copied to the container. COPY will simply copy these files as-is without any extraction.
# ADD will extract the archive automatically
ADD archive.tar.gz /path/to/extract/
# COPY will copy the archive as a single file
COPY archive.tar.gz /path/to/archive.tar.gz
Remote URL Support
ADD can download files from remote URLs and place them in the container, while COPY cannot handle remote sources.
# ADD can download from URLs
ADD http://example.com/file.zip /path/to/file.zip
# COPY cannot handle URLs - this would fail
# COPY http://example.com/file.zip /path/to/file.zip
Behavior with Directories
Both commands handle directories similarly, but COPY is more predictable when dealing with directory contents. ADD has some edge cases with directory handling that can be surprising.
Build Context Sensitivity
COPY is more strict about the build context - it only allows copying from the build context directory or its subdirectories. ADD is more flexible but can lead to unexpected behavior.
When to Use COPY
COPY should be your default choice for most file copying operations in Dockerfiles. Use COPY when:
- You need simple, predictable file copying
- You’re copying files that should NOT be extracted (like configuration files)
- You want to maintain transparency in your Dockerfile
- You’re copying local files that don’t require special handling
- You need better build cache invalidation behavior
COPY is preferred by the Docker community because it’s more explicit and has fewer hidden behaviors. When someone reads COPY in your Dockerfile, they know exactly what’s happening without needing to understand additional rules.
When to Use ADD
ADD has specific use cases where it provides value over COPY. Use ADD when:
- You need to extract compressed archives automatically
- You need to download files from remote URLs during build
- You want to reduce the number of layers in your Dockerfile
- You’re dealing with legacy Dockerfiles that already use ADD effectively
The automatic extraction feature can be particularly useful for reducing Dockerfile complexity. Instead of needing separate RUN commands to extract archives, ADD handles it automatically.
# Using ADD to extract and reduce layers
ADD application.tar.gz /app/
RUN cd /app && ./install.sh
# Alternative with COPY (more layers)
COPY application.tar.gz /tmp/
RUN tar -xzf /tmp/application.tar.gz -C /app/
RUN /app/install.sh
Best Practices
Prefer COPY for Most Cases
The Docker official documentation and community best practices recommend using COPY over ADD whenever possible. COPY’s behavior is more predictable and transparent.
Use ADD Judiciously
Only use ADD when you specifically need its extra functionality. Avoid using ADD just because “it works” - understand why you’re choosing it over COPY.
Combine with RUN Commands
Even when using ADD for extraction, you might still need RUN commands for post-extraction tasks like moving files or running installation scripts.
Consider Build Cache
Both COPY and ADD affect the build cache, but COPY’s simpler behavior can sometimes lead to more predictable cache invalidation patterns.
Be Explicit About File Types
If you use ADD for automatic extraction, make it clear in comments what’s happening, as this behavior isn’t obvious to all Docker users.
Examples and Use Cases
Simple File Copy
# Best practice - use COPY for simple files
COPY config.json /app/config/
COPY requirements.txt /app/
Archive Extraction
# Good use case for ADD - archive extraction
ADD source-code.tar.gz /app/source/
WORKDIR /app/source
Remote File Download
# Only ADD can handle remote URLs
ADD https://github.com/user/repo/archive/main.zip /tmp/repo.zip
RUN unzip /tmp/repo.zip -d /app/
Multi-stage Builds
In multi-stage builds, you can use ADD to copy extracted artifacts between stages:
# Stage 1: Build with ADD for extraction
FROM builder as build
ADD source.tar.gz /build/
RUN cd /build && make build
# Stage 2: Copy only what you need
FROM runtime
COPY --from=build /build/artifact /app/bin/
Performance Considerations
Build Time Impact
ADD’s automatic extraction can sometimes be faster than separate COPY + RUN tar commands, but the difference is often negligible. The main consideration is readability and maintainability.
Image Size
Both commands contribute to final image size, but ADD’s automatic extraction doesn’t inherently create smaller images than manual extraction with COPY + RUN commands.
Cache Efficiency
COPY’s simpler behavior can lead to more predictable cache hits. When you modify a file that COPY uses, Docker knows exactly what changed. ADD’s additional complexity can sometimes lead to unexpected cache behavior.
Conclusion
Key Takeaways
- COPY is simpler and more predictable - use it as your default choice
- ADD has special features for archive extraction and remote URLs
- Prefer COPY for transparency and explicit behavior
- Use ADD only when you specifically need its extra functionality
- Both commands affect build cache and image size
Practical Recommendations
- Start with COPY for all your file copying needs
- Only switch to ADD when you need archive extraction or remote URL downloading
- Document your use of ADD to make Dockerfile behavior clear
- Consider the trade-offs between convenience and transparency
- Test your Dockerfile behavior to ensure it matches expectations
Related Questions
- Can I use both COPY and ADD in the same Dockerfile? Yes, but it’s generally better to standardize on one when possible
- Does ADD work with all archive formats? ADD supports common formats like .tar, .tar.gz, .zip, etc.
- Is ADD deprecated? No, but it’s less commonly recommended than COPY for most use cases