When you search for “Dockerfile best practices,” one of the suggestions you will find is that you always use the COPY
instruction instead of the ADD
instruction when adding files into your Docker image.
This blog post will explore why this suggestion exists by providing additional detail on the functionality of these two instructions. Once you understand these concepts, you may find scenarios where you can benefit from ignoring the suggestion and using the ADD
command instead of COPY
.
Understanding file system build context
Before diving into the differences between ADD
and COPY
, it’s important to understand the concept of build context. The build context is the set of files and directories that are accessible to the Docker engine when building an image. When you run a docker build
command, Docker sends the content of the specified context directory (and its subdirectories) to the Docker daemon. This context forms the scope within which the COPY
and ADD
instructions operate.
COPY instruction
The COPY
instruction is straightforward and does exactly what its name implies: It copies files and directories from a source within the build context to a destination layer in the Docker image. This instruction can be used to copy both files and directories, and all paths on the host are relative to the root of the build context.
Syntax:
COPY <src>... <dest>
<src>
: The source files or directories on the host.<dest>
: The destination path inside the Docker image.
Key points
- Basic functionality:
COPY
only supports copying files and directories from the host file system. It does not support URLs or automatic unpacking of compressed files. - Security: Because
COPY
only handles local files, it tends to be more predictable and secure thanADD
, reducing the risk of unintentionally introducing files from external sources. - Use case: Best used when you need to include files from your local build context into the Docker image without any additional processing.
Example:
COPY ./app /usr/src/app
COPY requirements.txt /usr/src/app/
In this example, the contexts of the local app
directory are copied into the /usr/src/app
directory inside the Docker image being built. The second command copies the requirements.txt
file into the /usr/src/app
directory as well.
ADD instruction
The ADD
instruction provides the same functionality that the COPY
instruction does, but it also has additional functionality that, if misunderstood, can introduce complexity and potential security risks.
Syntax:
ADD <src>... <dest>
<src>
: The source files (directories or URLs).<dest>
: The destination path inside the Docker image.
Key points
- Extended functionality: In addition to copying local files and directories from the build context,
ADD
provides the following advanced functionality:- Handle URLs: When supplied as a source, the file referenced by a URL will be downloaded to the current Docker image layer at the supplied destination path.
- Extract archives: When supplied as a source,
ADD
will automatically unpack and expand archives to the current Docker image layer at the supplied destination path.
- Flexibility vs. security: Although
ADD
is more flexible, it does introduce risk. Downloading external URLs into the build process may allow malicious code or contents to be brought into the process. UsingADD
with archives may result in unintended consequences if you do not understand how it handles archives. - Use case:
ADD
should only be used when you need specific functionality that it provides and are willing to manage the potential security issues arising from this usage.
Example:
ADD https://example.com/file.tar.gz /usr/src/app/
ADD my-archive.tar.gz /usr/src/app/
In this example, the build process first downloads https://example.com/file.tar.gz
and extracts the contents into /usr/src/app
in the Docker image layer. In the next step, it takes the local file my-archive.tar.gz
and extracts it into the Docker image layer under /usr/src/app
.
When to use COPY vs. ADD
- For most use cases,
COPY
is the better choice due to its simplicity and security. This instruction allows you to transfer files and directories from your local context into the Docker image you are building. - Use
ADD
only when you need the additional capabilities it offers, but be mindful of potential security implications.
Remote contexts
In addition to traditional file system contexts, Docker also supports remote contexts, which can be particularly useful in cloud environments or for building images from code repositories directly. These include:
- Git repositories: You can specify a Git repository URL as the build context, allowing Docker to clone the repository and use its content as the context.
docker build https://github.com/username/repository.git#branch
- Remote URLs: Docker can use remote URLs for the build context. This is useful for building images directly from archives available online.
docker build http://example.com/context.tar.gz
- OCI images: You can use an OCI image as the build context, which is useful for using pre-built images as the starting point for new builds.
docker build oci://registry.example.com/image:tag
How ADD and COPY behave in remote contexts
Note that both ADD
and COPY
behave slightly differently when used in a remote context.
Using COPY with remote contexts
COPY
still operates within the scope of the build context, and can copy files and directories from the cloned repository into the Docker image. For example, when using a Git repository as the build context, COPY
can copy files and directories from the cloned repository into the Docker image. It does not support copying files from URLs or other remote sources directly.
Example with Git repository as build context:
# Using a Git repository as build context
COPY ./src /app/src
In this case, COPY
will copy the src
directory from the Git repository (the build context) to /app/src
in the Docker image.
Example with URL build context:
# Using an archive from a URL
COPY ./src /app/src
In this case, COPY
will copy the src
directory from the extracted archive (the build context) to /app/src
in the Docker image.
Example with OCI image as build context:
# Using an OCI image as build context
COPY /path/in/oci/image /app/path
In this case, COPY
will copy the contents from the specified path within the OCI image to the specified destination path in the Docker image.
Using ADD with remote contexts
The ADD
instruction can still be used to download files and extract archives as well as copy files from the build context. Note that all the caveats provided about the ADD
instruction above apply here as well.
Example with Git repository as build context:
# Using a Git repository as build context
ADD https://example.com/data.tar.gz /data
ADD ./src /app/src
In this example, ADD
will download and extract data.tar.gz
from the URL into the /data
directory in the Docker image. It will also copy the src
directory from the Git repository (the build context) to /app/src
in the Docker image.
Example with URL build context:
# Using an archive from a URL
ADD https://example.com/data.tar.gz /data
ADD ./src /app/src
In this example, ADD
will download and extract data.tar.gz
from the URL into the /data
directory in the Docker image. It will also copy the src
directory from the downloaded/unpacked URL (the build context) to /app/src
in the Docker image.
Example with OCI image as build context:
# Using an OCI image as build context
ADD https://example.com/data.tar.gz /data
ADD /path/in/oci/image /app/path
In this scenario, ADD
will download and extract data.tar.gz
from the URL into the /data
directory in the Docker image. It will also copy the contents from the specified path within the OCI image to the specified destination path in the Docker image.
COPY vs. ADD tl;dr:
- Prefer
COPY
: For most use cases,COPY
is the better choice due to its simplicity and security. Use it to transfer files and directories from your local context or a remote context like a Git repository to the Docker image. - Use
ADD
with caution: Opt forADD
only when you need its additional functionalities, like downloading files from URLs or automatically extracting archives (Figure 1). Always be mindful of the potential security implications when usingADD
.
Conclusion
Understanding the differences between ADD
and COPY
instructions in Dockerfiles and how they can be affected by build context can help you build more efficient and secure Docker images. Although COPY
offers a straightforward way to include local files, ADD
provides additional flexibility with the cost of increased complexity and potential security risks.
Learn more
- Read the Dockerfile reference documentation.
- Subscribe to the Docker Newsletter.
- Get the latest release of Docker Desktop.
- Vote on what’s next! Check out our public roadmap.
- Have questions? The Docker community is here to help.
- New to Docker? Get started.