COPY versus ADD in a Dockerfile
Choose ordinary copies, local archive extraction, remote downloads, or build-stage copies without relying on outdated cache advice.
Use COPY when you want ordinary file copying. Use ADD when you specifically need one of its additional source-handling features, such as extracting a local archive or retrieving a remote resource. Neither instruction is universally better; the important distinction is the behavior you intend.
Start with the archive distinction
COPY app.tar.gz /app/
ADD app.tar.gz /app/
COPY preserves the archive as a file. ADD normally extracts a recognized local tar archive into the destination. Recognition depends on its content, not just its filename extension. These are alternatives, not two steps you normally need together.
A remote HTTP archive is ordinarily downloaded as a file rather than automatically extracted. Newer Dockerfile frontends offer additional controls such as ADD --unpack; check your frontend's supported version before relying on them.
COPY can use more than the local context
The usual source is the build context, subject to .dockerignore. It cannot escape that context simply by using ../ in a path. However, COPY --from can copy from another build stage, an image, or a named build context:
COPY --from=builder /out/server /usr/local/bin/server
This fragment assumes a suitable builder stage or named source. It is inaccurate to describe COPY as restricted to local files in every form.
Remote ADD is a supported use case
Current Docker guidance also supports ADD for remote HTTP or Git resources. A trusted SHA-256 checksum can pin and verify an HTTP download with ADD --checksum=sha256:DIGEST URL DESTINATION; replace all placeholders with the verified values.
Do not assume an unchanged URL means BuildKit can never notice changed content. Equally, replacing ADD with a cached RUN curl instruction does not guarantee that the URL is downloaded again on the next build. Pin resource identity and understand the chosen builder's cache behavior.
Use RUN when you need a custom download sequence
For an image already containing curl, tar, and the destination directory:
RUN curl -fsSL https://example.com/tool.tar.gz -o /tmp/tool.tar.gz \
&& tar -xzf /tmp/tool.tar.gz -C /opt \
&& rm /tmp/tool.tar.gz
The URL is illustrative. In a real build, verify a trusted checksum before extraction. Downloading, extracting, and removing the temporary archive in one step avoids preserving that intermediate file in an earlier layer. Build secrets or SSH mounts are preferable to putting private credentials in image instructions.
FAQ
When should I prefer COPY?
For ordinary context files and stage outputs, its intent is straightforward. ADD's archive or remote behavior should be an explicit choice.
Does .dockerignore affect both?
It excludes local build-context paths from either instruction. It does not mean an unrelated remote URL or a separate stage's filesystem is filtered by that same file.
How do I make downloads reproducible?
Use immutable versions or commits and verified checksums, then test the resulting artifact. A mutable URL plus any caching instruction is not a reproducibility guarantee.
See the COPY and ADD reference and Docker build practices.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan