Reputation: 1918
I have a dockerfile like this:
FROM node:alpine
WORKDIR /app
COPY package.json .
RUN npm install
VOLUME [ "/app/node_modules" ]
COPY . .
ENTRYPOINT [ "npm" ]
CMD [ "run", "dev" ]
I build my image by using the command below:
docker build -t my-vue-app .
Then I run my container by using the command below:
docker run -v $(pwd):/app --name app -it --rm my-vue-app
It outputs a permission error:
error when starting dev server:
Error: EACCES: permission denied, mkdir '/app/node_modules/.vite'
at Object.mkdirSync (node:fs:1024:3)
at optimizeDeps (/app/node_modules/vite/dist/node/chunks/dep-efe32886.js:65416:21)
at runOptimize (/app/node_modules/vite/dist/node/chunks/dep-efe32886.js:69180:54)
at Server.httpServer.listen (/app/node_modules/vite/dist/node/chunks/dep-efe32886.js:69194:23)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
I override my entrypoint to access my container's file system to check permissions.
docker run -v $(pwd):/app --name app -it --rm --entrypoint /bin/sh my-vue-app
/app # ls -l | grep node_modules
I can see the owner and group of node_modules
is root
Output:
drwxr-xr-x 52 root root 4096 Mar 18 20:04 node_modules
All the other files have owner and group node
/app # ls -l
total 28
-rw-rw-r-- 1 node node 154 Mar 18 20:02 Dockerfile
-rw-r--r-- 1 node node 337 Mar 18 19:26 index.html
drwxr-xr-x 52 root root 4096 Mar 18 20:04 node_modules
-rw-r--r-- 1 node node 307 Mar 18 19:26 package.json
drwxr-xr-x 2 node node 4096 Mar 18 19:26 public
drwxr-xr-x 4 node node 4096 Mar 18 19:26 src
-rw-r--r-- 1 node node 156 Mar 18 19:26 vite.config.js
So, I wonder why does it happen and what can I do to solve it? Also one thing is, when I use node:lts
instead of node:alpine
, user and group of node_modules
is still root
but it works fine.
Currently node:lts
is node:14.16.0
.
Upvotes: 1
Views: 4078
Reputation: 158908
You should remove all mention of volumes of any sort in this entire setup. Do not declare a VOLUME
for the node_modules
directory; do not replace the image's code using a docker run -v
option.
Once you do this, the image will be self-contained. You can push it to a registry if you'd like, and docker run
it on another system without separately downloading the code. Bind-mounts can cause host user IDs and build-time user IDs to get confused, which is likely what's happening in your setup. The VOLUME
will also cause Docker to leak anonymous volumes, and in a Compose-based setup will likely cause any changes in your package.json
file to get ignored.
This approach won't support live reloading inside a container, but it's very easy to install Node on the host (and you may have it already), and a host-based Node will work much better with IDEs and other tooling.
(I would also combine the ENTRYPOINT
and CMD
into a single CMD
. If nothing else, this will simplify the "run a debugging shell" case by not requiring the docker run --entrypoint
option; you can docker run --rm -it my-vue-app /bin/sh
.)
Upvotes: 2