Difference between the COPY and ADD commands in a Dockerfile
When creating Dockerfiles, it’s often necessary to transfer files from the host system into the Docker image. These could be property files, native libraries, or other static content that our applications will require at runtime.
The Dockerfile specification provides two ways to copy files from the source system into an image: the COPY and ADD directives.
Here we will look at the difference between them and when it makes sense to use each one of them.
Sometimes you see COPY or ADD being used in a Dockerfile, but you should be using COPY 99% of the time. Here’s why.
COPY and ADD are both Dockerfile instructions that serve a similar purpose. They let you copy files from a specific location into a Docker image.
COPY takes in a source and destination. It only lets you copy in a local or directory from your host (the machine-building the Docker image) into the Docker image itself.
COPY <src> <dest>
ADD does that same but in addition, it also supports 2 other sources.
- A URL instead of a local file/directory.
- Extract tar from the source directory into the destination.
ADD <src> <dest>
In most cases, if you’re using a URL, you download a zip file and then use the RUN command to extract it. However, you might as well just use RUN and curl instead of ADD here, so you chain everything into 1 RUN command to make a smaller Docker image. A valid use case for ADD is when you want to extract a local tar file into a specific directory in your Docker image. This is exactly what the Alpine image does with ADD rootfs.tar.gz /.
If you are copying local files to your Docker image, always use COPY because it’s more explicit.
While functionality is similar, the ADD directive is more powerful in two ways as follows:
- It can handle remote URLs
- It can also auto-extract tar files.
Let’s look at these more closely.
First, the ADD directive can accept a remote URL for its source argument. The COPY directive, on the other hand, can only accept local files.
Note: Using ADD to fetch remote files and copying is not typically ideal.
This is because the file will increase the overall Docker Image size. Instead, we should use curl or wget to fetch remote files and remove them when no longer needed.
Second, the ADD directive will automatically expand tar files into the image file system. While this can reduce the number of Dockerfile steps required to build an image, it may not be desired in all cases.
Note: The auto-expansion only occurs when the source file is local to the host system.
When to use ADD or COPY: According to the Dockerfile best practices guide, we should always prefer COPY over ADD unless we specifically need one of the two additional features of ADD. As noted above, using ADD command automatically expands tar files and specific compressed formats, which can lead to unexpected files being written to the file system in our images.
Conclusion: Here we have seen the two primary ways to copy files into a Docker image: ADD and COPY. While functionally similar, the COPY directive is preferred for most cases. This is because the ADD directive provides additional functionality that should be used with caution and only when needed.
Let’s compare the differences in a tabular form:
|COPY COMMAND||ADD COMMAND|
|COPY is a docker file command that copies files from a local source location to a destination in the Docker container.||ADD command is used to copy files/directories into a Docker image.|
|Syntax: COPY <src> <dest>||Syntax: ADD source destination|
|It only has only one assigned function.||It can also copy files from a URL.|
|Its role is to duplicate files/directories in a specified location in their existing format.||ADD command is used to download an external file and copy it to the wanted destination.|
|If we want to avoid backward compatibility, we should use the COPY command.||ADD command is less usable than the COPY command.|