As an experienced full-stack developer, I regularly author Dockerfiles to build optimized images for deploying applications. Two of the most common Dockerfile instructions – COPY and ADD – serve similar purposes at first glance. However, understanding the key differences is essential for writing effective, transparent Dockerfiles.
In this comprehensive guide, I breakdown when to use COPY versus ADD based on their unique capabilities, best practices, use cases, and more.
Dockerfile COPY and ADD By Example
Before diving into specifics on COPY and ADD, let‘s first see each in action in sample Dockerfiles.
Here is an example utilizing COPY:
FROM ubuntu:latest
WORKDIR /app
COPY . .
CMD python app.py
And here is an example using ADD instead:
FROM alpine:latest
ADD http://example.com/app.tar.gz /usr/local/app
CMD /usr/local/app/start.sh
In these simplified examples:
- COPY: simply copies local files into image
- ADD: downloads app tarball from URL and extracts into image
The syntax is very similar, but the capabilities and best practices differ significantly.
COPY vs ADD Usage Statistics
Examining over 1 million public Docker images, approximately 75% utilized COPY compared to only 25% leveraging ADD according to research from Anchore. This aligns with recommended best practices of favoring COPY over ADD where possible.
| Instruction | Usage in Dockerfiles |
| COPY | 75% |
| ADD | 25% |
However, ADD can provide simplification in certain use cases where downloading and extracting archives in one command is advantageous. The key is understanding the core differences in order to thoughtfully choose between them.
Considering Immutability and Caching Behaviors
A key difference between COPY and ADD is that ADD supports remote URLs as the source, while COPY only allows local files. Consider this Dockerfile using ADD:
ADD http://example.com/app.tar.gz /usr/local/app
This can introduce external dependencies and make the final image contents unpredictable:
- The remote tarball contents could change unexpectedly over time
- The same ADD command may pull down different files on each image build
This goes against best practices of immutable Docker images – you generally want fixed image contents from build to build.
COPY only allows local sources, ensuring immutable and consistent copies each Dockerfile run. Additionally, COPY does not cache source files at all while ADD caches remote resources so unchanged sources are not re-downloaded.
Therefore if aiming for strict reproducibility, avoid ADD with remote sources in favor of COPY.
Official Best Practice Recommendations
According to Docker‘s official documentation:
"Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious."
This aligns with my recommendation to standardize on COPY in most cases due to its simplicity and transparency into final image contents. Only leverage ADD where advanced features like decompression or remote files are absolutely required.
Metadata Differences
An additional consideration with ADD vs COPY is their handling of metadata for copied files:
- COPY preserves metadata from sources for ownership, permissions, etc
- ADD sets permissions to 600 and ownership to root regardless of source metadata
Therefore if maintaining accurate permissions/ownerships for the files in the image is important, COPY is likely the better option over ADD here as well.
Diagramming Operation Flows
Here is a diagram highlighting the conceptual differences in flows between COPY and ADD:

As illustrated, COPY only supports the simple file copy path while ADD has additional built-in capabilities and modifications during the process.
Visualizing the flows in this way reiterates why COPY tends to be recommended from transparency and immutability perspectives.
Developer Opinions from Experience
Based on writing many Dockerfiles myself, I almost always default to COPY first unless I know I specifically need ADD‘s extras.
The main scenario I routinely use ADD is for copying compressed archives into images then expanding them. This simplifies a multi-step copy/extract process into a single command.
However, outside of specific cases like this, COPY is my instruction of choice due to its simple and transparent file copying behavior.
Keeping Dockerfiles easy to understand should be a priority – COPY aligned with this principle. The extra magic of ADD feels clever at first, but can obscure what is actually happening during builds.
Security Considerations of Remote Sources
Allowing remote URLs as sources with ADD introduces security risks not present with local COPY sources:
- Remote resources could execute malicious code during extraction
- Sources could be temporarily modified to inject ill-intentioned files
- TLS/SSL issues could compromise downloads via man-in-the-middle attacks
These compound the best practice around using COPY instead of ADD wherever possible – restricting to purely local sources limits exposure to security issues.
For endpoint images distributed widely, ADD‘s remote capabilities become an antipattern due toDOWNLOAD these expanded attack surfaces. Keeping builds purely local with COPY makes dockerfiles more securable.
Quick Reference: Key Differences Table
Here is a table summarizing the key points differences discussed between COPY and ADD to use as a quick reference:
| COPY | ADD | |
| Source Types | Local files only | Local files or remote URLs |
| Transparency | Very transparent | Some internal magic |
| Immutability | Fully immutable sources | Remote URLs can unpredictably change |
| Caching Behavior | No caching | Caches remote resources |
| Metadata Handling | Preserves permissions and ownership | Overrides with root user and permissions |
| Security | Only safe local sources | Risks from remote sources |
Keeping this quick comparison handy simplifies deciding when to use COPY vs ADD while authoring Dockerfiles.
The Right Tool for the Right Job
As with all tools, the importance comes from leveraging COPY and ADD purposefully based on their capabilities, not just using one over the other uniformly.
For transparent, simple, immutable file copying, COPY certainly seems to be the preferable choice according to guidelines and my own experience.
However, ADD can simplify more advanced application image builds where remote sources or archives are present. As long as you understand and plan for the potentially altered functionality, ADD remains a handy Dockerfile tool.
The key is acknowledging that COPY and ADD overlap significantly, but ultimately have divergent design goals. Distinguishing use cases where one makes more sense over the other leads to optimized images.
Hopefully this guide has shed some light helping identify when to properly apply each tool! Let me know if you have any other questions.


