Q: What is the difference between COPY and ADD in a Dockerfile?
Answer:
Both instructions copy files from the build context into the image, but ADD has extra (often unwanted) functionality.
COPY — Simple File Copy
Does exactly one thing: copies files or directories from the build context into the image filesystem. It's transparent and predictable.
COPY requirements.txt /app/
COPY src/ /app/src/
ADD — Copy with Extras
ADD does everything COPY does, plus two additional features:
- Auto-extracts compressed archives (
.tar,.tar.gz,.tgz,.bz2,.xz) into the destination directory. - Fetches files from remote URLs (like
wget).
# Auto-extracts the tarball into /app/
ADD app.tar.gz /app/
# Downloads a file from the internet
ADD https://example.com/config.json /etc/app/config.json
Why You Should Almost Always Use COPY
[!WARNING] The Docker official best practices guide explicitly recommends using
COPYoverADDin almost all cases.
Reasons:
- Predictability:
COPYhas no hidden side effects. WithADD, a developer might not realize their.tar.gzfile will be auto-extracted. If you want the archive as-is (e.g., to extract it manually later),ADDwill silently break your intent. - Security:
ADDfrom a URL does not verify SSL certificates and doesn't support authentication. UseRUN curlorRUN wgetinstead for better control. - Cache invalidation: Remote URL fetches with
ADDcan cause unpredictable cache behavior since Docker cannot know if the remote file has changed.
Rule of Thumb
- Use
COPYfor all local file copies (99% of cases). - Use
ADDonly when you explicitly need tar auto-extraction. - Use
RUN curlorRUN wgetfor downloading remote files.