What's the difference between COPY and ADD?

4 minbeginnerdockerfilecopyadd

Quick Answer

COPY does one thing: copies files/directories from the build context into the image. Simple, predictable, and the generally recommended default. ADD does everything COPY does, plus two extra behaviors: it can automatically extract local .tar archives into the destination, and it can fetch a remote URL directly into the image. Docker recommends COPY unless you specifically need one of ADD's extra behaviors, since ADD's implicit magic — especially auto-extraction — has surprised people in ways that caused real bugs.

Detailed Answer

COPY — simple, explicit, predictable

COPY package.json package-lock.json ./
COPY src/ ./src/

Copies files or directories from the build context straight into the image's filesystem, with no extra behavior. What you see is exactly what happens.

ADD — COPY, plus automatic extraction and remote URL fetching

# ADD automatically extracts a LOCAL tar archive into the destination
ADD myapp.tar.gz /app/

# ADD can fetch directly from a URL
ADD https://example.com/config.json /app/config.json

The first example is the behavior that most often surprises people. If the source is a recognized local archive format — .tar, .tar.gz, .tar.bz2ADD automatically unpacks it into the destination. COPY would just copy the compressed archive file itself, unextracted. Docker's own documentation calls out this "maybe it extracts, maybe it doesn't, depending on file type" behavior as a source of confusion.

Why COPY is the recommended default

  • Predictability. COPY does one simple thing, with no hidden conditional logic based on file type.
  • ADD's remote-URL fetching is generally discouraged. Fetching a remote file directly in a Dockerfile instruction means the build result depends on a URL you don't control at build time — worse for reproducibility. The fetched file also isn't automatically cleaned up if it's only needed transiently. A RUN curl ... && ... in the same layer, or a multi-stage build, gives more explicit control.
  • ADD's auto-extraction is useful in only one scenario: unpacking a local tarball as part of assembling the image. That's legitimate, but narrow enough that you should reach for ADD deliberately for that purpose, not out of habit. A remote URL fetch in particular is better done as an explicit RUN curl/wget, or a multi-stage build step that verifies the artifact, than via ADD's implicit behavior.