ryanwhocodes Jun 25, 2018 · 3 min read

Dockerfile COPY vs ADD - Key Differences and Best Practices

Learn why you should use COPY over ADD in Dockerfiles and Docker's recommendations for how to use them effectively.

Docker has two similar Dockerfiles instructions, COPY and ADD, which are both used to include files in an image. This article will explain their key differences as well as the reasons why using COPY is the best practice, unless you want to auto-extract a local tar file into the image.

Contents

COPY

This copies one or many local files or folders into the destination within your Docker image.

  • COPY <source>... <destination>

  • COPY ["<source>",... "<destination>"] (this form is required for paths containing whitespace)

Docker’s Dockerfile Reference: COPY

An example Dockerfile that uses COPY

This is how you would use COPY in a Dockerfile for a Ruby app.

    FROM ruby:2.5.1
    WORKDIR /usr/src/app
    COPY Gemfile Gemfile.lock ./
    RUN bundle install
    COPY . .
    CMD ["./your-daemon-or-script.rb"]

It builds up the image in layers, starting with the parent image ruby:2.5.1, defined using FROM.

The Docker instruction WORKDIR defines a working directory for the COPY or ADD instructions that follow it.

By copying the Gemfiles followed by RUN bundle install , an image layer is created with the installed Ruby Gems, which can be cached. The last two Docker instructions copy the app’s files into the image and set the default command using CMD.

This means if you change any of the app’s files, you can rebuild the Docker image using the cached parent and intermediate layers. This is much more efficient than building all of them from scratch.

ADD

This instruction has similar syntax to COPY.

  • ADD <source>... <destination>

  • ADD ["<source>",... "<destination>"] (this form is required for paths containing whitespace)

Docker’s Dockerfile Reference: ADD

As well as copying local files and directories into the destination within the Docker image, it has some additional features:

  • If <source> is a local tar archive in a recognized compression format, then it is automatically unpacked as a directory into the Docker image. For example: ADD rootfs.tar.xz /

  • If the <source> is a URL, then it will download and copy the file into the destination within the Docker image. However, Docker discourages using ADD for this purpose.

Dockerfile best practice for copying from a URL

Docker suggests that it is often not efficient to copy from a URL using ADD, and it is best practice to use other strategies to include the required remote files.

Because image size matters, using ADD to fetch packages from remote URLs is strongly discouraged; you should use curl or wget instead. That way you can delete the files you no longer need after they’ve been extracted and you don’t have to add another layer in your image.Dockerfile Best Practices

For example, you should avoid doing things like:

    ADD http://example.com/big.tar.xz /usr/src/things/
    RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
    RUN make -C /usr/src/things all

And instead, do something like:

    RUN mkdir -p /usr/src/things \
        && curl -SL http://example.com/big.tar.xz \
        | tar -xJC /usr/src/things \
        && make -C /usr/src/things all

For other items (files, directories) that do not require ADD’s tar auto-extraction capability, you should always use COPY.

Find out more

The official Dockerfile reference goes into further detail on COPY, ADD and other Dockerfile instructions.

When writing your Dockerfiles, Docker’s webpage Best practices for writing Dockerfiles covers many more tips for how to structure your Dockerfiles, images, and containers efficiently.