services:
api:
build: .
volumes:
- .:/app
The bind mount hides the image's node_modules. A bind mount puts a folder from your computer (the host) inside the container.
Here is what happens. The image ran npm ci, so it has node_modules inside /app. When you mount the host folder over /app, it hides everything the image had at that path, including node_modules. Then one of two things goes wrong:
- The host has no
node_modules, so the module is missing. - The host has
node_modules, but they were installed for the host OS. Native modules may not work on Linux in the container.
The usual fix is a second mount just for /app/node_modules, such as the anonymous volume - /app/node_modules. The more specific mount wins for that path. So the container keeps the modules installed in the image, and the rest of the code comes from the host.
Also exclude node_modules in .dockerignore. Compose Watch is a newer alternative. It copies (syncs) changed files into the container instead of using a bind mount.
- A mount hides the files that the image already had at that path.
- The bind mount hides the image's node_modules folder.
- Modules from the host may be built for a different OS.
- Add a separate volume for /app/node_modules to keep the image's modules.
- Bind mounts (https://docs.docker.com/engine/storage/bind-mounts/)docs.docker.com
- Docker Compose (https://docs.docker.com/compose/)docs.docker.com