COPY are two similar
Dockerfile instructions which let you add content to your images at build time. Whereas
COPY is a straightforward source to destination copy,
ADD includes extra functionality for working with archives and remote URLs.
COPY is the simpler of the two instructions. It accepts two arguments, a source and destination:
COPY example.txt /example/dir/example.txt
The source path will be copied from your Docker host into the container’s filesystem. The built image will include the copied file or directory at the specified destination path.
COPY works with all files and directories but source paths are restricted to those within your active build context. The context is set when you run
docker build . # OR docker build /path/to/context
The instruction automatically creates the destination directory in the container when it doesn’t already exist. If you include a trailing slash (
/), Docker treats the destination as a directory and will place the source file inside it.
You can use wildcards such as
*.jpg in the source path destination to match a set of files. These expressions will be parsed using the Go
Copied files have a UID and GID of 0 by default. This can be customized with the optional
--chown flag which accepts UIDs, GIDs, and names. It runs
chown on the copied files once they’re inside the container:
COPY --chown=my-user:my-group example.txt /example.txt
COPY also supports a
--from flag. This modifies the source path to refer to another container image, instead of your local build context. It also works with multi-stage builds to pull in artifacts created by earlier build stages.
# Copies /usr/bin/composer from the composer:latest image COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Multi-stage build example # Stage 1: Copies example.scss from working directory into node:latest image # Stage 2: Copies example.css built in stage 1 into the final image (based on httpd:latest) FROM node:latest AS sass COPY example.scss . RUN npm install -g node-sass && node-sass example.scss example.css FROM httpd:latest COPY --from=sass /example.css example.css
--from flag must refer to a named stage that’s listed earlier in the
Dockerfile. When there’s no matching stage, Docker assumes you’re referencing an image instead. You’ll hit a build error if the image can’t be pulled.
ADD has the same syntax as
COPY, accepting source and destination paths. There’s no support for
--from but you can use
ADD is capable of downloading remote file URLs. Specifying a publicly accessible URL as the source path will download that file and add it to the container image. The destination path’s modified time (
mtime) will be set to the value of the
Last-Modified header in the download’s HTTP response.
ADD can also extract tar archives, including archives compressed with gzip, bzip2, and xz. Specifying a compatible archive as the source path will unpack its contents into the specified container directory. The existing contents of the directory will be retained.
Archive detection is based on the actual file contents, not the filename or extension. You can use any genuine archive file without naming it
The ability to automatically extract archives simplifies adding software packages distributed as tar files to your container images. Supplying a tar path to
COPY would copy the compressed archive file as-is, not its contents. You’d need to use a
RUN instruction to manually decompress the file.
The behaviors around
COPY apply to
ADD to. Except for remote URLs, source paths must exist in your build context. The container’s destination path will be automatically created when it doesn’t exist using Docker’s rules for path resolution.
ADD are two closely related but distinctly different instructions you can use when writing a
Dockerfile. As their feature sets overlap, you might be wondering which is the “best” to use by default.
According to Docker’s own best practices guide, you should reach for
COPY unless you need the extra capabilities of
ADD is an opaque operation that adds magic to the copying process.
ADD when it’s actually needed helps to communicate your intentions. Otherwise, you risk getting team members into the habit of using
ADD which could have disastrous consequences. An unintentional
ADD my-archive.tar . instead of
COPY my-archive.tar could cause confusion and broken builds when the archive’s contents show up in your container, instead of the archive itself.
You should also carefully consider when it’s appropriate to use
ADD with remote URLs. It can be more efficient to use
wget with a
RUN instruction as this helps facilitate image layer caching. An
ADD instruction will always invalidate the cache for all following build stages when the file at a remote URL changes.
Where possible, it’s good practice to delete copied files after they’ve been used. If you’re downloading or extracting a software installer, deleting the one-time binary after you’ve run it will help to slim down your final image.