I’m working on a Vue.js project that I haven’t touched in about a year. When I try to run my build command using Docker, I encounter permission errors related to NPM cache files.
Here’s the command I’m using:
docker run --rm -p 3000:3000 -v "${PWD}:/workspace" -v /workspace/node_modules myapp:latest npm run compile
This results in an error that looks like this:
npm ERR! code EACCES
npm ERR! syscall open
npm ERR! path /home/appuser/.npm/_cacache/tmp/a12345b6
npm ERR! errno -13
npm ERR!
npm ERR! Your cache folder has files owned by root
npm ERR! To permanently resolve this issue, please run:
npm ERR! sudo chown -R 1000:1000 "/home/appuser/.npm"
Unfortunately, my container lacks sudo, preventing me from running the suggested fix command.
I attempted to use the --user root flag to access the container as root and execute the chown command. While it works temporarily, once I exit and restart the container, the file ownership reverts back to root.
Here is my Dockerfile:
FROM node:lts-alpine
WORKDIR /workspace
RUN chown appuser:appuser /workspace
USER appuser
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "npm", "run", "dev" ]
Why don’t the permission changes persist between container sessions? Is there something I need to understand about how Docker manages file permissions?
Your volume mount is causing an ownership mismatch due to how Docker handles file permissions. When you mount with -v "${PWD}:/workspace", it overrides the ownership settings you established in your Dockerfile. Unfortunately, the container cannot permanently change the permissions of host directories. I faced a similar issue previously. You can resolve it in two ways: first, create a .npmrc file in your project root with cache=/workspace/.npm-cache, which allows npm to use a cache directory within your mounted workspace where permissions work correctly. Ensure you add .npm-cache to your .gitignore. Alternatively, consider avoiding the volume mount for node_modules altogether. This allows Docker to install dependencies during build time rather than at runtime, improving efficiency by leveraging Docker’s layer caching.
This happens because Docker messes with file permissions between your host and container. When you mount with -v "${PWD}:/workspace", the files keep their host ownership, which clashes with your container’s appuser. Skip the chown headaches - just run your container with the --user flag instead. Get your user ID with id -u, then run: bash docker run --rm -p 3000:3000 --user $(id -u):$(id -g) -v "${PWD}:/workspace" -v /workspace/node_modules myapp:latest npm run compile This makes the container process run with your host user’s permissions, so no more permission conflicts. Your chown changes don’t stick because each docker run spawns a fresh container - any changes you make at runtime disappear when it stops.
Another quick fix: clear your npm cache completely before installing. Add RUN npm cache clean --force right after the USER appuser line in your dockerfile. Also try mounting a named volume for the npm cache instead of using the container filesystem - something like -v npm-cache:/home/appuser/.npm. This way the cache sticks around but with proper permissions.