docker-pm2 icon indicating copy to clipboard operation
docker-pm2 copied to clipboard

Start container as non-root user

Open soosap opened this issue 8 years ago • 6 comments

First of all, thanks for the image. Following best practices I learned that it's best to not start containers as a root user.

When I switch to the node user though, I get "permission denied" error:

Error: EACCES: permission denied, open '/usr/local/lib/node_modules/pm2/node_modules/array-unique/index.js'
    at Object.fs.openSync (fs.js:651:18)
    at Object.fs.readFileSync (fs.js:553:33)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/pm2/node_modules/micromatch/lib/utils.js:13:16)
    at Module._compile (module.js:569:30)

Is there a way to start this container as non-root user, i.e. assuming user "node". When doing so, for what files and directories do I need to change ownership to that new user?

soosap avatar Jun 27 '17 15:06 soosap

@Unitech any thought on this?

simonepri avatar Jul 08 '17 10:07 simonepri

I ran into this problem as well.

As a Linux n00b I discovered several issues with this:

  1. npm has been installed by the root user in the original node:alpine image
  2. installing pm2 therefor is only possible using the root user as well
  3. executing pm2 as a different user is not possible because it has been installed as root, so it gives you "permission denied"

To run NPM and PM2 using a different user I've created my own image with the following tweaks:

RUN chown -R USER:GROUP $(npm config get prefix)/lib/node_modules
RUN chown -R USER:GROUP /usr/local/bin/pm2

jvduf avatar Jul 15 '17 13:07 jvduf

@Unitech maybe we can add the @jvduf workaround to the readme. What do you think about?

simonepri avatar Jul 15 '17 13:07 simonepri

I've been experimenting some more...

This might be a cleaner option and is also the suggested solution as per https://docs.npmjs.com/getting-started/fixing-npm-permissions

RUN mkdir -p /home/app/.npm-global/bin \
    && npm config set prefix '/home/app/.npm-global' \
    && npm install -g pm2

ENV PATH=/home/app/.npm-global/bin:${PATH}

[edit: exporting the path was incorrect, so added it through ENV command]

jvduf avatar Jul 15 '17 13:07 jvduf

This is part of my Dockerfile:

RUN addgroup -g 9999 app && adduser -u 9999 -G app -D app -s /bin/bash \
    && apk upgrade --update \
    && apk add --no-cache \
       bash bash-completion \
       git

COPY ./bash/.bash* /home/app/

USER app
ENV HOME=/home/app/
WORKDIR $HOME

RUN mkdir -p /home/app/.npm-global/bin \
    && npm config set prefix '/home/app/.npm-global' \
    && npm install -g pm2

ENV PATH=/home/app/.npm-global/bin:${PATH}

jvduf avatar Jul 15 '17 13:07 jvduf

Update on 2020, The solution of @jvduf works until I want to log PM2 output to file (by adding output and error option in ecosystem.config.js), under is my Dockerfile:

Rest is same with @jvduf
...
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]

When I run, it'll say permission error on where log files will be created. And I figure out that, even I install and run PM2 under an user (using USER app), the log files created by PM will be owned by the host user and group whom we use to run the command docker-compose up. I don't experience this problem on Mac but it occurs on my Ubuntu server. I have no idea why PM2 can create log files in another user's permission, even if we explicitly run it by a non-root user.

Because of that reason, solution is set user id and group in Docker to be same as user on host system:

  • In host system, run id -u and id -g to find out your user and group IDs
  • Replace those values in Dockerfile (replace where 9999 located)

Note:because User ID and Group ID with value 1000 are in used by node user inside container, so if your host user ID and group are also 1000, it'll print out user ID 1000 is in used during building Docker image, then you have 2 options:

  • Option 1: change your host user ID and group ID to different ID (you usually may not prefer to do this)
  • Option 2: in Dockerfile, change user to node by setting USER node, then all headache problems are gone.

maitrungduc1410 avatar Aug 23 '20 14:08 maitrungduc1410