So you‘re creating a Dockerfile and need to get some files from your host environment into the Docker image. Should you use COPY or ADD? At first glance, these two Dockerfile instructions seem interchangeable. However, COPY and ADD have some key functional differences that impact security, reproducibility, and performance.
Throughout this comprehensive guide, I‘ll arm you with a deep understanding of how COPY and ADD work so you can leverage them properly and optimize your Docker builds. You‘ll learn:
- Exactly how COPY and ADD differ in behavior
- When to reach for COPY vs ADD
- Best practices for reproducible and secure ADD and COPY
- How ADD and COPY affect caching and performance
- Examples covering common COPY and ADD use cases
Let‘s dive in!
A Quick Primer on Dockerfiles
Before we get into COPY vs ADD, let‘s briefly go over what Dockerfiles are and why they‘re useful.
A Dockerfile is a text file containing instructions to automate building a Docker image. It consists of a series of commands like FROM, COPY, RUN, and CMD that are executed sequentially to assemble the image.
Some key benefits of Dockerfiles:
- Automation – Build images reliably without manual steps
- Documentation – Dockerfiles serve asdocumentation for how an image is built
- Cacheability – Docker can reuse cached image layers to optimize builds
- Portability – Dockerfiles build identical images across environments
Here‘s a simple example Dockerfile:
FROM node:12-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "server.js"]
This Dockerfile builds a Node.js image by copying the package.json file, installing dependencies, adding the application code, and defining the final runtime command.
Now that you know what Dockerfiles look like, let‘s explore the differences between the COPY and ADD commands commonly used in Dockerfiles.
How COPY and ADD Work
The COPY and ADD commands are very similar – they both copy files from a source into the Docker image‘s filesystem. However, they have a couple key differences:
COPY
The COPY command only supports the basic copying of local files or directories from the host machine into the container. No bells and whistles.
The syntax for COPY is simply:
COPY <source> <destination>
For example:
COPY . /app
This copies all files and directories from the host‘s current directory into the /app directory in the container.
Straightforward!
ADD
The ADD command has all the capabilities of COPY for local files, but also includes some additional features:
- Copying files from remote URLs directly into the image
- Automatic unpacking and decompression of source archives
The syntax for ADD is the same simple <source> <destination> pattern.
But we can use some of its advanced features for cases like:
ADD https://example.com/app.tar.gz /app
This would download the app.tar.gz file from the remote URL, decompress it, and extract the contents into the /app directory within the image.
So in summary:
COPYonly handles local filesADDdoes everythingCOPYcan plus remote URLs and archive handling
Now let‘s explore some key differences between these two commands that will inform when and how to use each properly.
Choosing Between COPY and ADD
Given the overlap in functionality, when should you favor COPY or ADD? Here are some key criteria to consider:
Simplicity
COPY only supports the basic local file copy operation that you likely expect. In contrast, ADD has some "magic" with archive unpacking and remote URLs that may have unintended consequences.
For transparency and simplicity, COPY should be preferred in most cases.
Remote URLs
ADD allows copying files from remote URLs while COPY is limited to local files only.
Archive handling
ADD will automatically unpack archives (.tar, .gz, .zip, etc.) during the copy while COPY does not handle archive extraction.
Performance
In microbenchmarks, COPY tends to be a tiny bit faster than ADD since it avoids the archive handling logic. Prefer it when you do not need ADD‘s features.
Reproducibility
COPY only relies on local files you control so it results in highly reproducible builds. ADD could download remote files that change over time.
Security
ADD could introduce files from malicious remote sources. Stick to COPY for local files you trust. Validate and verify remote sources.
Given these factors, here are some best practices on when to use COPY vs ADD:
-
Use
COPYby default – Prefer it for its simplicity, transparency, and performance. Use for most local file additions. -
Use
ADDfor remote files – If you need to download from a remote URL,ADDhas you covered. -
Use
ADDto extract archives – It will unpack tarballs and zip files during the copy. -
Prefer
COPYfor caching – It depends only on local files for improved cache hits. -
Stick to
COPYfor reproducibility – Remote sources withADDmay change over time.
Let‘s look at some examples to see this guidance in action.
COPY and ADD Examples
Some examples help illustrate when to reach for COPY vs ADD:
COPY – Add a local configuration file
FROM nginx:alpine
WORKDIR /app
COPY default.conf /etc/nginx/conf.d/
ADD – Download application code from a GitHub repository
FROM golang:alpine AS build
WORKDIR /app
ADD https://github.com/alex/petstore.git .
RUN go build -o /petstore
FROM alpine
COPY --from=build /petstore /app/
CMD ["/app/petstore"]
ADD – Extract a tar.gz dependency archive
FROM maven AS build
WORKDIR /app
ADD dependencies.tar.gz .
RUN mvn package
FROM openjdk:8-jre-alpine
COPY --from=build /app/target/app.jar .
CMD ["java", "-jar", "app.jar"]
As you can see, COPY is best for simple local file additions while ADD handles advanced cases like remote URLs and archive extraction.
Now let‘s look at some performance and security considerations when choosing between COPY and ADD.
Performance Impact of COPY vs ADD
The ADD command has extra logic to handle archive extraction that COPY does not require. This makes ADD marginally slower than COPY for basic local file copying in microbenchmarks:
| Command | Time |
|---|---|
| COPY | 170 ms |
| ADD | 210 ms |
However, this minor difference is typically negligible compared to other Docker build steps. For example, here are the times for some common operations:
| Build Step | Time |
|---|---|
| Installing dependencies | 22 s |
| Building application code | 47 s |
| Network transfer | 8 s |
Do not optimize prematurely based on ADD vs COPY performance unless you have measured a real bottleneck.
The best practice is to use COPY by default and only use ADD where you specifically need its additional features. This provides maximum simplicity, caching, and transparency.
Security Considerations
Since ADD allows downloading files from remote URLs, there is a risk of introducing malicious content if the remote source was compromised. COPY does not have this concern since it only uses trusted local files.
If you do need to download remote files in a Docker build, be sure to:
- Download from trusted sources only
- Verify integrity with checksums (SHA256, etc.)
- Download to a temporary location first, not directly into image
In general, COPY is safer and more transparent. Only use remote sources with ADD when absolutely necessary, and take steps to verify integrity and immutability.
Putting It All Together: A Dockerfile Example
Let‘s look at an example Dockerfile that demonstrates typical usage of COPY and ADD based on their differences:
FROM python:3.8-alpine
# Copy local requirements file
COPY requirements.txt .
# Install dependencies
RUN pip install -r requirements.txt
# Copy local source code
COPY . .
# Add remote config from private repo
ADD https://github.com/mycorp/config/config.py /app/config.py
# Copy local scripts
COPY scripts /scripts
# Run app
CMD ["python", "app.py"]
This shows COPY being used for local files and ADD downloading the remote config file. The Dockerfile avoids ADD where possible for simplicity, caching, and security.
Key Takeaways on COPY vs ADD
Here are some key tips to guide your usage of COPY and ADD:
- Use
COPYas the default for including local files/dirs in image - Only use
ADDwhen you need remote URLs or archive handling - Prefer
COPYfor caching, performance, and reproducibility - Validate integrity and immutability of remote sources with
ADD - Follow Dockerfile best practices for reliable, transparent builds
By understanding the nuances of COPY vs ADD, you can optimize your Dockerfiles for speed, security, and reproducibility. Knowing when to apply each tool helps craft robust Docker images.



