Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

npm throws Operation not permitted #17

Closed
haggen opened this issue May 8, 2015 · 17 comments
Closed

npm throws Operation not permitted #17

haggen opened this issue May 8, 2015 · 17 comments

Comments

@haggen
Copy link

haggen commented May 8, 2015

Using dinghy, when I try to npm install something, it complains:

npm ERR! Error: EPERM, chown '/shared/node_modules/gulp/package.json'
npm ERR!  { [Error: EPERM, chown '/shared/node_modules/gulp/package.json']
npm ERR!   errno: 50,
npm ERR!   code: 'EPERM',
npm ERR!   path: '/shared/node_modules/gulp/package.json',
npm ERR!   fstream_finish_call: 'chown',
npm ERR!   fstream_type: 'File',
npm ERR!   fstream_path: '/shared/node_modules/gulp/package.json',
npm ERR!   fstream_class: 'FileWriter',
npm ERR!   fstream_stack: 
npm ERR!    [ '/usr/lib/nodejs/fstream/lib/writer.js:305:19',
npm ERR!      '/usr/lib/nodejs/graceful-fs/polyfills.js:143:7',
npm ERR!      'Object.oncomplete (evalmachine.<anonymous>:107:15)' ] }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

npm ERR! System Linux 3.18.11-tinycore64
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "gulp"
npm ERR! cwd /shared
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.21
npm ERR! path /shared/node_modules/gulp/package.json
npm ERR! fstream_path /shared/node_modules/gulp/package.json
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! fstream_finish_call chown
npm ERR! code EPERM
npm ERR! errno 50
npm ERR! stack Error: EPERM, chown '/shared/node_modules/gulp/package.json'
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:305:19
npm ERR! fstream_stack /usr/lib/nodejs/graceful-fs/polyfills.js:143:7
npm ERR! fstream_stack Object.oncomplete (evalmachine.<anonymous>:107:15)
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /shared/npm-debug.log
npm ERR! not ok code 0

It used to work well on boot2docker, even when using nfs.

@haggen haggen changed the title Operation not permitted upon trying to change files from a container Can't change files from mounted volume inside a container May 8, 2015
@haggen haggen changed the title Can't change files from mounted volume inside a container npm throws Operation not permitted May 9, 2015
@codekitchen
Copy link
Owner

hm I don't know why npm install would be trying to chown this file, but I can give you some background on why it's failing: dinghy configures the NFS volume to "squash" all files to be owned by your user on the host OSX machine. It didn't originally, it ran NFS operations as root on the host machine, this change was discussed in #15

The consequence of this is that you aren't writing to the NFS share as root, and you typically won't have permission to chown files. Ideally, I'd love to be able to configure the NFS share to just ignore chown commands, like virtualbox built-in file shares do, but that isn't possible without modifications to the NFS server code.

As far as your specific problem, is the npm install running as root? If so, modifying your container to run as a non-root user would potentially fix the issue.

I wouldn't be totally opposed to a configuration setting to let you choose whether dinghy enables root squashing or not, since both have their advantages.

@haggen
Copy link
Author

haggen commented May 13, 2015

Hey @codekitchen thanks a lot for the heads up! I'm going to try changing the container user later and report back to you.

@0ff
Copy link

0ff commented May 24, 2015

Had the exact same problem running wercker, as I don't know how to configure it to not run as root inside the box, I have added a new step right before npm install is run, that would solve my problem (effectively running npm installas my host's user):

    # NOTE: you might want to adjust the uid and gid values for your user
    - script:
        name: downgrade to mac user
        code: |
          useradd -u 501 -g 20 wercker
          mkdir /home/wercker
          /usr/bin/sudo -u wercker -s
          export HOME=/home/wercker

@codekitchen
Copy link
Owner

@haggen I'm going to close this, let me know of you're still hitting issues.

@MrMMorris
Copy link

@haggen I actually just hit a similar issue and wanted to share my solution.

I have a nodejs app. I run it in a nginx container as it is just static site code built with nodjs. Because of this, developers can't just attach to the container and run npm because it's not actually installed. What happens when you need to update a module?

Well, I run a separate container that is the official node image. I mount my local git repo into it and then I can run npm command inside the container. Great! but then I run into your issue:

Error: EPERM, chown '/app/node_modules/watchify/package.json'

I don't want to have to mess around with starting a container, mounting the repo, adding users/changing permissions, I want it automated! So this is what I came up with:

docker run --rm -u $UID -it -w /app -v $PWD /client/container/npm:/.npm -v $PWD:/app node:0.10-slim npm install watchify@3.3.1 --save

-u sets the uid of the user running the container to my local uid which means that I don't run into Error: EPERM, chown

the first -v is specific to my case because npm wants to create a /.npm folder. You may not need it depending on if you keep a .npm folder in your repo, but if you do, just have a empty npm directory in your local repo that you can mount to /.npm (-v can't mount dotfiles as it doesn't have permission to view them)

the second -v mounts everything in my local repo to /app so that my changes show up in my local repo even after the container is gone

-w just sets the WORKDIR

This essentially is a containerized way of running commands so you don't need to install something like nodejs and npm on your local. You could take it one step further and use the docker run command as an alias or make task.

Hope this can help someone

@markshust
Copy link

This still does appear to be an issue. I worked around it by doing something like the following:

  echo "Installing node modules..."
  cp /src/package.json /root/
  cd /root && npm install -q
  echo "Node modules installed. Syncing back to /src/node_modules..."
  rsync -rlzuIO --ignore-errors /root/node_modules/ /src/node_modules > /dev/null 2>&1
  rm -rf /root/node_modules /root/package.json

@ryanmt
Copy link

ryanmt commented Dec 2, 2015

Switching user in the Dockerfile to a non-root user fixed it for me.

@kilpatty
Copy link

@ryanmt How were you able to switch the user to a non-root user in the Dockerfile?

@MrMMorris
Copy link

@kilpatty
Copy link

@MrMMorriss I attempted that, but I'm now getting an even uglier exit than before. Still getting 'chown permission denied, Please try running as root' on npm install

@ryanmt
Copy link

ryanmt commented Feb 5, 2016

@Skilgarriff
USER is the command. I've often seen prerequisite useradd steps, and it might be necessary to run a chown before the npm install.

@kilpatty
Copy link

kilpatty commented Feb 5, 2016

@ryanmt Turns out it was an issue with maproot. Dinghy does not map the root to 0 which causes some issues when trying to run any privileged command when trying to use that command on Volumes mounted with NFS.

@wchrisjohnson
Copy link

More background on this issue: docker/machine#1817 I'm specifically hitting this issue ATM with npm and it's looking like I'm going to have to use virtual box ... ;-(

@trakos
Copy link

trakos commented Apr 13, 2016

There's a comment here: npm/npm#3565 (comment) showing a nice way to overcome that - you can make chmod do nothing by using LD_PRELOAD.

You can do it for the entire container in Dockerfile. First make sure you've gcc installed, and then add:

RUN echo "int chown() { return 0; }" > preload.c && gcc -shared -o /libpreload.so preload.c && rm preload.c
ENV LD_PRELOAD=/libpreload.so

This simply makes chmod think it actually did something and succeed, so npm is all happy and confident it did a good job.

You can also do it just for one command - just call npm install this way (again, you need gcc):

echo "int chown() { return 0; }" > preload.c && gcc -shared -o preload.so preload.c && LD_PRELOAD=$PWD/preload.so npm install && rm preload.c preload.so

radmiraal pushed a commit to SimplyAdmire/docker-flow-development that referenced this issue Aug 14, 2016
This uses a bash script as entrypoint that tricks the chown
command so it will not throw 'operation not permitted' errors
on nfs shares.

@see codekitchen/dinghy#17
@TomFrost
Copy link

TomFrost commented Sep 23, 2016

This is driving me nuts. In our dev environments, my team mounts their home folder to /root due to needing access to the NPM login token, AWS credentials, shared NPM cache, etc stored there. This worked well with docker implementations where root took ownership of new files (we've used dlite with success in the past, but lack of maintenance is making that one tough to use now). Under dinghy's model of setting root to use the executing user/group's access levels, I get this every time I NPM install, even if I delete ~/.npm first:

npm ERR! Error: EPERM: operation not permitted, chown '/root/.npm/_locks'
npm ERR!     at Error (native)
npm ERR!  { Error: EPERM: operation not permitted, chown '/root/.npm/_locks'
npm ERR!     at Error (native)
npm ERR!   errno: -1,
npm ERR!   code: 'EPERM',
npm ERR!   syscall: 'chown',
npm ERR!   path: '/root/.npm/_locks' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! Linux 4.4.17-boot2docker
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "install" "-g" "node-gyp"
npm ERR! node v6.3.1
npm ERR! npm  v3.10.5
npm ERR! path npm-debug.log.737059936
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall open

So I did a code-dive and discovered the :custom_nfs_export_options preference. "Eureka!" I thought. So I popped open my system's /etc/exports and grabbed this line that dlite injected: /Users -network 192.168.64.0 -mask 255.255.255.0 -alldirs -maproot=root:wheel and converted that to what it looked like dinghy's bundled NFS needed. I ended up with these prefs:

---
:preferences:
  :proxy_disabled: false
  :fsevents_disabled: false
  :create:
    provider: xhyve
  :custom_nfs_export_options: rw,alldirs,maproot=root:wheel

After a dinghy restart, I confirmed that my machine-nfs-exports-dinghy file had the appropriate settings. Hurrah!

...but my in-container npm install still failed. I got the same error as before, and this one:

npm ERR! Error: EACCES: permission denied, open 'npm-debug.log.737059936'
npm ERR!     at Error (native)
npm ERR!  { Error: EACCES: permission denied, open 'npm-debug.log.737059936'
npm ERR!     at Error (native)
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'open',
npm ERR!   path: 'npm-debug.log.737059936' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

I really, really do not want to do the chown hack mentioned above if there's an nfs configuration that can restore the old functionality. Any idea why my solution didn't take care of this?

EDIT: Neeeevermind. Rather than maproot=root:wheel, I did anonuid=0,anongid=0. Worked like a charm. I don't get the dinghy fanciness of keeping everything under my local user's ownership, but at least my native npm modules build now.

@luctus
Copy link

luctus commented Nov 25, 2016

I'm using the passenger-ruby22 base image and I had this line in my Dockerfile:

RUN bower install --allow-root --config.interactive=false --verbose --force

which was giving me that error. I fixed it setting the user to someone different than root, as follows:

RUN setuser app bower install --allow-root --config.interactive=false --verbose --force

(The app user is the user that comes with my base image)

@Carl-Meyer
Copy link

This is driving me nuts. In our dev environments, my team mounts their home folder to /root due to needing access to the NPM login token, AWS credentials, shared NPM cache, etc stored there. This worked well with docker implementations where root took ownership of new files (we've used dlite with success in the past, but lack of maintenance is making that one tough to use now). Under dinghy's model of setting root to use the executing user/group's access levels, I get this every time I NPM install, even if I delete ~/.npm first:

npm ERR! Error: EPERM: operation not permitted, chown '/root/.npm/_locks'
npm ERR!     at Error (native)
npm ERR!  { Error: EPERM: operation not permitted, chown '/root/.npm/_locks'
npm ERR!     at Error (native)
npm ERR!   errno: -1,
npm ERR!   code: 'EPERM',
npm ERR!   syscall: 'chown',
npm ERR!   path: '/root/.npm/_locks' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! Linux 4.4.17-boot2docker
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "install" "-g" "node-gyp"
npm ERR! node v6.3.1
npm ERR! npm  v3.10.5
npm ERR! path npm-debug.log.737059936
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall open

So I did a code-dive and discovered the :custom_nfs_export_options preference. "Eureka!" I thought. So I popped open my system's /etc/exports and grabbed this line that dlite injected: /Users -network 192.168.64.0 -mask 255.255.255.0 -alldirs -maproot=root:wheel and converted that to what it looked like dinghy's bundled NFS needed. I ended up with these prefs:

---
:preferences:
  :proxy_disabled: false
  :fsevents_disabled: false
  :create:
    provider: xhyve
  :custom_nfs_export_options: rw,alldirs,maproot=root:wheel

After a dinghy restart, I confirmed that my machine-nfs-exports-dinghy file had the appropriate settings. Hurrah!

...but my in-container npm install still failed. I got the same error as before, and this one:

npm ERR! Error: EACCES: permission denied, open 'npm-debug.log.737059936'
npm ERR!     at Error (native)
npm ERR!  { Error: EACCES: permission denied, open 'npm-debug.log.737059936'
npm ERR!     at Error (native)
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'open',
npm ERR!   path: 'npm-debug.log.737059936' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

I really, really do not want to do the chown hack mentioned above if there's an nfs configuration that can restore the old functionality. Any idea why my solution didn't take care of this?

EDIT: Neeeevermind. Rather than maproot=root:wheel, I did anonuid=0,anongid=0. Worked like a charm. I don't get the dinghy fanciness of keeping everything under my local user's ownership, but at least my native npm modules build now.

Thank you so much! This helped me solve this problem as well!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests