How Can I Exclude a Directory in a Docker COPY Command?

Introduction

When working with Docker, it’s common to use the COPY command to transfer files and directories from the host machine into the container. However, what if you want to exclude a specific directory, such as node_modules, during the copy process? This can become necessary to avoid bloating the docker image with unnecessary files or improve build performance.

Understanding the Problem

The COPY command in Docker copies files and directories from the source path on the host machine to the destination path within the container. By default, it includes all files and subdirectories within the source directory. However, there may be situations where we want to exclude certain directories, such as those containing large dependencies or generated code, to optimize build time or reduce image size.

The Solution

Docker does not provide an explicit way to exclude directories with the COPY command. However, there are a few workarounds to achieve this:

1. Using a .dockerignore File (if Applicable)

A .dockerignore file can be created in the source directory to specify files and directories that should be excluded when building the image. This file follows the same syntax as the .gitignore file used in Git, allowing you to use patterns to define exclusions. For example, to exclude the node_modules directory, you can add the following line to the .dockerignore file:

node_modules

2. Using Multiple COPY Instructions

If a .dockerignore file is not suitable or you need more granular control over exclusions, you can use multiple COPY instructions. This involves creating a separate COPY instruction for each file or directory you want to include, excluding the ones you want to leave out. For instance, to copy all files except those in the node_modules directory, you can use the following commands:

COPY [^n]* .
COPY n[^o]* .
COPY no[^d]* .

3. Using a Multi-Stage Build with Exclusions

Another option is to use a multi-stage build, where you can exclude the directory in an intermediate stage before copying into the final image. This approach allows you to perform specific operations, such as removing the excluded directory, before building the final image. Here’s an example:

FROM ruby AS builder
COPY app/ app/
# Do stuff with app
RUN rm -Rf app/assets

FROM ruby AS publish
COPY --from=builder app app

Discussion

While these methods provide solutions for excluding directories in Docker’s COPY command, it’s important to consider the following:

  • Using a .dockerignore file is only effective if you don’t need the excluded files in any stage of the build.
  • Using multiple COPY instructions can become tedious if you have a large number of exclusions.
  • Multi-stage builds require more configuration and can add complexity to your Dockerfile.

Conclusion

The best approach to exclude directories in Docker’s COPY command depends on your specific needs and requirements. Carefully choose the method that aligns with your project’s goals and optimization strategies. By leveraging these techniques, you can streamline your Docker builds, reduce image size, and improve performance.