Skip to content

Dockerfile — COPY vs ADD


You’ve or may have used COPY in every Dockerfile so far without a second thought. There’s a second instruction that does almost the same thing — ADD — and it’s been sitting there the whole time, unused. This is a short one: what ADD does differently, and why COPY was still the right call every single time.

What They Share

Both move files from your build context into the image. For the plain case — a file, going to a path — they’re identical:

COPY index.html .
ADD index.html .

Either line produces the exact same layer. If this were the whole story, the instruction wouldn’t need a second name.

What ADD Does Extra

ADD has two tricks COPY doesn’t:

It can fetch a URL directly:

ADD https://example.com/setup.sh /app/setup.sh

It auto-extracts local tar archives:

ADD project.tar.gz /app/

Copy a .tar.gz with ADD, and it lands in the image already unpacked. COPY would just place the archive file itself, untouched.

Why COPY Wins Anyway

Both extras sound convenient, and both are exactly why ADD is usually the wrong choice:

  • The URL fetch skips your build context entirely. Nothing about the download shows up as a file you can inspect beforehand, there’s no checksum, and the request happens fresh on every uncached build. A plain RUN curl at least makes the download an explicit, visible step — ADD hides it inside an instruction that looks like a simple file copy.
  • The auto-extraction is a silent behavior change. ADD some.tar.gz /app/ and COPY some.tar.gz /app/ produce genuinely different images, and nothing about reading ADD tells you which files a plain COPY wouldn’t have carried across. That’s a bad kind of surprise for anyone reading the Dockerfile later — including future you.

Note

Docker’s own documentation recommends COPY for anything that’s just moving files, and reserves ADD for the rare case where you specifically want auto-extraction. Not “never use ADD” — just “don’t reach for it out of habit.”

Wrapping Up

COPY does one thing, predictably, every time — that’s the whole appeal. ADD does that same thing plus two extra behaviors that quietly change what ends up in your image, which is exactly why every Dockerfile in this series has used COPY. Default to it, and only reach for ADD when you specifically need a local archive extracted on the way in.

Last updated on