Confusion with node_modules being ignored by .dockerignore
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The main source of confusion is that .dockerignore only affects the build context sent to docker build. It does not delete files already created inside the image, and it does not control what bind mounts later place into the running container.
What .dockerignore Actually Does
When you run docker build ., Docker sends a build context to the daemon. That context is basically the set of files from the chosen directory that Docker is allowed to see for COPY and ADD instructions.
.dockerignore filters that context before the build begins.
So if your .dockerignore contains:
then the host machine's node_modules directory is not sent to the build context.
That means this Dockerfile will not copy host node_modules into the image:
But that does not mean the image or container will never contain node_modules.
Why node_modules Still Appears
There are two very common reasons node_modules still exists.
The first is that the Dockerfile installs dependencies inside the image.
Even if .dockerignore excludes the host node_modules, the RUN npm ci step creates /app/node_modules inside the image filesystem. That is normal and usually desirable.
The second reason is bind mounts in development.
That mount overlays /app with your host directory at runtime. If your host has node_modules, the container sees them. If your host does not have node_modules, the bind mount can hide the image's /app/node_modules entirely. This is the part that surprises people most.
Build-Time Versus Run-Time Is the Real Distinction
A good mental model is:
- '
.dockerignoreaffects build-time file transfer' - '
RUN npm ciaffects the image filesystem during build' - volume mounts affect what the container sees at run time
These are three separate stages. Problems happen when they are treated as one mechanism.
A Good Node.js Docker Pattern
For production images, a standard pattern is:
- ignore host
node_modules - copy only manifest files first
- run
npm ciin the image - copy application source afterward
Example:
And the matching .dockerignore:
This keeps the build context small and avoids copying host-installed binaries that may be incompatible with the target container OS.
Why Context Location Matters
.dockerignore is read from the build context root, not from wherever you wish it had been. If you run:
the build context is . and Docker uses .dockerignore from that root directory.
If you instead run:
then the context is docker/, and only a .dockerignore in that directory matters.
Many "Docker ignored my ignore file" bugs are actually context-path mistakes.
Development Containers Need Extra Care
In local development, many teams mount the project folder into the container to get live reload. That is fine, but it changes the node_modules behavior.
A common workaround is to mount the source code while keeping node_modules in a named volume or in a different path.
This prevents the host bind mount from clobbering the container's installed dependencies.
Common Pitfalls
The biggest mistake is expecting .dockerignore to remove files created by RUN npm install or RUN npm ci. It only filters files from the host build context.
Another mistake is forgetting that a bind mount can hide files already present in the image.
A third issue is building from the wrong context directory, which makes the wrong .dockerignore file apply or no ignore file apply at all.
Finally, copying host node_modules into Linux containers from macOS or Windows is usually the wrong idea because native dependencies may be built for the wrong platform.
Summary
- '
.dockerignoreonly controls what files from the host are sent todocker build.' - It does not prevent
npm ciinside the image from creatingnode_modules. - Bind mounts can override what the running container sees, including hiding image-installed dependencies.
- The build context directory determines which
.dockerignorefile is used. - For Node.js images, ignore host
node_modulesand install dependencies inside the image. - In development, use volumes carefully so source-code mounts do not break dependency layout.

