I am writing a Dockerfile to containerize my Node.js application. I want to use the COPY command to move my entire project folder into the image, but I need to exclude the node_modules and .git directories to keep the image size small and avoid permission issues. Since the COPY instruction doesn't seem to have an "exclude" flag, how can I achieve this efficiently? Is there a specific configuration file I should use, or do I have to copy every subdirectory individually?
3 answers
For Dockerfiles, always stick to .dockerignore. It’s a "set it and forget it" solution that ensures your node_modules never accidentally end up in your production image.
The standard and most efficient way to handle exclusions in Docker is by using a .dockerignore file. Much like a .gitignore file, you place this in the root of your build context (the same folder as your Dockerfile). In this file, you simply list the names of the directories you want to skip, such as node_modules or dist. When you run COPY . . in your Dockerfile, the Docker CLI will automatically filter out any files or folders listed in .dockerignore before sending the build context to the Docker daemon.
This not only keeps your image clean but also significantly speeds up the build process because it reduces the amount of data being sent to the daemon.
Using .dockerignore is definitely the right move for build-time exclusions. However, if I am using docker cp to move files into an already running container rather than building a new image, is there an equivalent "exclude" flag for the command line, or would I be forced to use a tar pipe to filter the files on the fly?
Steven, unfortunately, the docker cp command is very basic and does not support an exclude flag or .dockerignore logic. The "pro" way to do this is exactly what you suspected: using a tar pipe. You can run tar -cvz --exclude='dir_to_skip' . | docker exec -i my_container tar -xvz -C /target_path. This compresses the files, filters the directory you don't want, and streams the result directly into the container in one efficient operation.
I agree with Nancy. I spent a long time trying to write complex RUN rm -rf commands inside my Dockerfile before I realized that .dockerignore handles it much more elegantly. It also prevents those deleted files from hanging around in the intermediate layers of your image, which is crucial for security and storage.