Docker ADD vs COPY

Before you begin

In this tutorial, we’ll learn how to use and the difference between ADD and COPY Docker build commands. A GNU Linux/Mac OS machine and Docker will be required to follow this tutorial.

Common ADD and COPY capabilities

These commands allow you to copy files/directories from your host directly into a Docker image.

Copying files

# Dockerfile

COPY script_copy.sh /tmp
ADD script_add.sh /tmp

Previous commands are copying script_copy.sh and script_add.sh to the /tmp directory on the Docker image:

$ docker run -it testing_add_copy ls -la /tmp
>
total 12
drwxrwxrwt  2 root root 4096 Oct  3 09:53 .
drwxr-xr-x 35 root root 4096 Oct  3 09:53 ..
-rwxrwxr-x  1 root root  415 Oct  3 09:53 script_copy.sh
-rwxrwxr-x  1 root root  415 Oct  3 09:53 script_add.sh

Copying folders

# Dockerfile

COPY my_folder /tmp
# or
ADD my_folder /tmp

Checking the results:

$ docker build -t testing_add_copy . && docker run -it testing_add_copy ls -la /tmp
...
-rwxrwxr-x  1 root root  415 Oct  3 09:53 my_file.txt

As you can imagine, my_file.txt is the content inside of my_folder.

If you need to copy the folder itself you could do it by adding the name of the folder in the destination like the following example:

# Dockerfile

COPY my_folder /tmp/my_folder
# or
ADD my_folder /tmp/my_folder

Checking the results:

$ docker run -it testing_add_copy ls -la /tmp
...
drwxr-xr-x. 3 root root 4096 Oct  3 09:53 my_folder

If you need to copy files/directories from your host to a running container rather than to an image you can read the following post: How to copy files to or from a Docker container.

Docker ADD vs COPY

Basically Docker ADD command has two extra capabilities more than the COPY instruction:

  1. Automatic TAR extraction.
     # Dockerfile
    
     ADD scripts.tar.gz /tmp
    

    tar file will only be unpacked if its compression has one of the following formats: identity, gzip, bzip2 or xz.

  2. Allows the src to be an URL. If so, ADD will fetch files from it. If the src is a local URI the behaviour will be the same as Docker COPY.
     # Dockerfile
    
     ADD http://www.example.com/script.sh /tmp
    

Important note! Dockerfile ADD cannot decompress and fetch a remote URL at the same time. If you try to fetch a remote compressed file, will be not decompressed just fetched.

Docker COPY vs ADD

Following Best practices for writing Dockerfiles we should use ADD only when TAR extraction capability is needed otherwise is better to use COPY for the following reasons:

  • TAR extraction and remote URL support sometimes are not obvious and could easily end up to a mistake.
  • Fetching files and delete them need an extra layer. To prevent that is recommended to use GNU Wget or CURL instead of ADD instruction.
  • Docker COPY command can be used together with --from in a multi-stage build scenario to copy files from previous build stages to the current build stage. Example:
    # Dockerfile
    
    FROM node AS builder
    
    WORKDIR /opt/app
    
    RUN node -v
    RUN npm -v
    
    COPY . /opt
    
    RUN npm init -y
    
    ...
    
    FROM nginx:1.17-alpine
    
    COPY --from=builder /opt/app /usr/share/nginx/html
    
    ...
    

    Previous command copies the app folder build in previous stage to the current one in a folder ready to be serverd by Nginx. Using multi-stage build and COPY --from makes the resulting image smaller because it doesn’t include all the redundant files as a result of running node and npm build packages.

  • Having said all that, COPY is simpler than ADD resulting in a more controlled behaviour.

This post has been all about copying files during Docker build time. If you need to copy files once the containers are running we have another post called “How to copy files to or from a Docker container”.

Finally, make sure to use a .dockerignore file to define a better Docker build context.

Finally, you should definitely take a look at these books to fuel your Docker knowledge: