Dockerfile COPY vs ADD: Which to Use

By 

Published on

4 min read

Split comparison of Dockerfile COPY and ADD instructions moving source files into an image layer

When a Docker image needs application code, configuration, or a release archive, both COPY and ADD can place files in the image. For an ordinary local file, COPY app.py /app/ and ADD app.py /app/ produce the same result, but the instructions differ once archives, remote sources, or build stages are involved.

Use COPY for local files and artifacts from other build stages. Use ADD when you want automatic tar extraction or need BuildKit to fetch a remote HTTP or Git source. This guide compares both instructions and explains which one fits each case.

What COPY Does

COPY takes files or directories from the build context and places them at a destination inside the image:

dockerfile
COPY requirements.txt /app/
COPY src/ /app/src/

An archive copied this way stays an archive, and a source path cannot point outside the build context. Two options cover common permission needs by setting ownership and mode as the files are copied:

dockerfile
COPY --chown=appuser:appgroup --chmod=644 config.yml /app/

COPY can also read from a named context, another image, or an earlier stage in a multi-stage build. The --from option is commonly used to move compiled artifacts into a smaller production image:

dockerfile
COPY --from=builder /app/target/server /usr/local/bin/server

What ADD Does

For local files and directories, ADD behaves much like COPY. It also understands local tar archives, remote URLs, and Git repository sources.

When the source is a local tar archive, either uncompressed or compressed with gzip, bzip2, or xz, ADD extracts it into the destination instead of copying the archive file:

dockerfile
ADD rootfs.tar.gz /

Docker detects an archive from its contents, not its filename. A file named rootfs.tar.gz that does not contain a recognized tar archive is copied without an extraction error. When you need the archive itself inside the image, use COPY, or use ADD --unpack=false with Dockerfile syntax 1.17 or later.

For remote sources, ADD can download an HTTP or HTTPS URL. BuildKit supports --checksum so the build fails if the downloaded content does not match the expected SHA-256 digest. Here is a checksum-verified download:

dockerfile
# syntax=docker/dockerfile:1
ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d \
    https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz \
    /tmp/linux-0.01.tar.gz

Remote tar archives are downloaded without extraction by default. Dockerfile syntax 1.17 added --unpack=true for builds that should download and extract a remote tar archive in one instruction.

ADD can also clone a Git repository from an HTTPS or SSH address. A branch, tag, commit, or subdirectory can be selected in the URL, and --checksum can pin a Git source to a commit. These behaviors are covered in the official Dockerfile ADD reference .

Key Differences

Source or behaviorCOPYADD
Local files and directoriesCopies themCopies them
Local tar archiveKeeps the archiveExtracts it by default
Remote HTTP or HTTPS URLNot supportedDownloads it
Remote Git repositoryNot supportedClones it
Checksum for a remote sourceNot applicable--checksum
Remote tar extractionNot supported--unpack=true
Build stage, named context, or image--fromNot supported

Choosing Between COPY and ADD

Use COPY for application source code, configuration, static assets, and other ordinary files from the build context. It states the intent directly and ensures that an archive remains intact. COPY --from is also the correct choice for moving artifacts between build stages or importing files from another image.

Use ADD when its source-aware behavior is part of the task. Local tar extraction is useful for assembling a root filesystem or installing a vendored release archive without storing the compressed archive in its own image layer.

For example, this instruction extracts a local application archive directly into /opt/app/:

dockerfile
ADD app-1.4.2-dist.tar.gz /opt/app/

For remote artifacts, current Docker build best practices favor ADD with --checksum because BuildKit can cache the remote source precisely and verify its contents. A RUN instruction with curl or wget is still appropriate when you need custom request handling or additional processing. Keep verification, extraction, and cleanup in the same RUN instruction so temporary files do not remain in a separate layer.

Conclusion

Choose COPY for local content and multi-stage artifacts. Choose ADD when you need automatic tar extraction or a checksum-verified remote source. For the complete image-building workflow, see our guide on building Docker images with a Dockerfile , and keep the Docker cheatsheet nearby for the rest of the instruction set.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page