Docker Node permission denied when using non-root user - node.js

When I try to run node as a docker container with a non-root user, it says:
ERROR: for node Cannot start service node: OCI runtime create failed: container_linux.go:348: starting container process caused "chdir to cwd (\"/foo\") set in config.json failed: permission denied": unknown
My docker-compose.yml looks like this:
...
node:
image: node:latest
container_name: my_node_thingy
ports:
- "3003:3000"
user: "node"
working_dir: /foo
volumes:
- /var/project:/foo/
command: "node /foo/app.js"
networks:
- my-network
...
When I set "root" as the user, it works fine but when creating a new one by doing the following, the container wont start:
adduser --disabled-password --gecos '' node
adduser node sudo
echo "node ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/node
Could someone please explain to me how to set up the user properly?

If you have permission to do chmod -R 777 /var/project, please do it, then everything is ok, you can continue use user: node.
If you do not have permission, why not clone your code in a folder which you have a permission then repeat above?
If you still persist to say you want to make the Dockerfile suitable for more rugged environment. Then you may have to use gosu.
You need to define a new dockerfile inherit from node:latest, in the dockerfile, install gosu.
Something like follows:
FROM node:latest
RUN GOSU_SHA=5ec5d23079e94aea5f7ed92ee8a1a34bbf64c2d4053dadf383992908a2f9dc8a \
&& curl -sSL -o /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture)" \
&& chmod +x /usr/local/bin/gosu \
&& echo "$GOSU_SHA /usr/local/bin/gosu" | sha256sum -c -
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
And, in entrypoint.sh you need first use gosu to change the permission of /foo, then start your nodejs project.
Finally, remove command in docker-compose.yml.
Maybe change the permission of volume at host is the quicker way.

Related

Create a Docker-Postgres-Container on Linux with docker-compose and a bind-mount, such that the dir contains the pgres-data and is not owned by root

This question has been asked countless times in countless places, but so far, I haven't found a single answer that actually works.
What I want:
I want to create a Docker-Container (using Docker-Compose and only a single startup without manually having to chmod or chown in between), that contains a Postgres-Database. The contents of this database should be bind-mount to my local system, eg. to the directory ./data, as would theoretically be possible using volumes:\n ./data:/var/lib/postgresql/data. If one das that, however, the ./data directory will be owned by root (or by systemd-coredump because that's the user with the id 999), and I don't want that. I want to be able to move the whole thing to another location without root-rights, so the resulting directory should be owned by my user (1000:1000).
This has been asked countless times, but no answer I tried worked. Either the directory created was empty on the host (presumably because the container didn't have rights to write as my user), or it was only accessible by root, or it would have worked with a volume (!=bind-mount), or it would have worked when chown-ing in between, but that's all not what I want.
What I found so far:
https://github.com/docker-library/postgres/issues/116: None of these solutions worked for me.
when I eg. run PG_DATA=$(pwd)/data docker run -d --name psql -e POSTGRES_PASSWORD=DB_PASS -e POSTGRES_USER=DB_USER -e POSTGRES_DB=DB_NAME -e PGDATA=$PG_DATA -v $PG_DATA:/var/lib/postgresql/data postgres:11.5-alpine (krzysztof-adamski's solution), the ./data directory stays empty on my host.
shewless's solution also doesn't work:
docker run -it --rm --user "$(id -u):$(id -g)" -v $(pwd)/data:/var/lib/postgresql/data -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/mydata postgres returns mkdir: cannot create directory ‘/var/lib/postgresql/data/mydata’: Permission denied
while docker run -it --rm --user "$(id -u):$(id -g)" -v $(pwd)/data:/var/lib/postgresql/data/pgdata -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/pgdata postgres gives me the error chmod: changing permissions of '/var/lib/postgresql/data/pgdata': Operation not permitted chmod: changing permissions of '/var/run/postgresql': Operation not permitted The files belonging to this database system will be owned by user "chris". This user must also own the server process..
other combinations of PGDATA and the mountpoint were also not fruitful.
https://stackoverflow.com/a/66502465/5122790:
This answer theoretically works, however I do not want to chmod in between and then change my docker-compose.yml file. There is a comment to this blogpost: https://suedbroecker.net/2020/06/23/run-a-postgressql-container-as-a-non-root-user-in-openshift/, which suggests creating a custom Dockerfile where the correct user and permissions are set, however this didn't work for me as well (...maybe because my docker-compose.yml was incompatible with that - I tried various combinations of removing/adding some lines with these files:
Dockerfile:
FROM postgres:latest
# see https://stackoverflow.com/a/66502465/5122790
RUN mkdir temp
RUN groupadd non-root-postgres-group
RUN useradd non-root-postgres-user --group non-root-postgres-group
RUN chown -R non-root-postgres-user:non-root-postgres-group /temp
RUN chmod 777 /temp
#RUN chown -R non-root-postgres-user:non-root-postgres-group /usr/local/var/postgres
USER non-root-postgres-user
docker-compose.yml:
version: "3.8"
#see https://forums.docker.com/t/data-directory-var-lib-postgresql-data-pgdata-has-wrong-ownership/17963/26
services:
sidb:
container_name: arg
# image: postgres:latest
build: . #see https://stackoverflow.com/a/66502465/5122790
volumes:
- ./django_data/db:/tmp/data:rw
- /etc/passwd:/etc/passwd:ro
ports:
- "5433:5432"
environment:
- POSTGRES_DB=siddata
- POSTGRES_USER=siddata
- POSTGRES_PASSWORD=siddata
#- PGDATA=/tmp/data #see https://stackoverflow.com/a/61884120/5122790 https://stackoverflow.com/a/66502465/5122790
#user: 1000:1000
but I didn't manage to get any of that working.
I found a ton of other answers, but NONE of them provided working code (either a pure docker-command that works on Unix (Ubuntu in my case), or a working docker-compose-file plus dockerfile if needed. There are many smart answers, maybe I'm too stupid to connect the dots, but if somebody could give me a working solution I would be vastly thankful.
Also, as far as I see it, the documentation at https://github.com/docker-library/docs/tree/master/postgres#arbitrary---user-notes even seems to be wrong - their second work-around docker run -it --rm --user "$(id -u):$(id -g)" -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword postgres does not work on my machine and again gives the error fixing permissions on existing directory /var/lib/postgresql/data ... initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted.
There are also a ton of closed issues (https://github.com/docker-library/postgres/issues/427, https://github.com/docker-library/postgres/issues/476, https://github.com/docker-library/postgres/issues/264, https://github.com/moby/moby/issues/22075, https://github.com/docker-library/postgres/issues/116) and people seem to keep figuring it out, but so far I have not found one solution that works for my demands (docker-compose, no chmoding in between, works on Linux, with a bind-mount, dir not owned by root and not empty).
i got it like this:
postgres:
image: postgres
user: 1000:1000
environment:
POSTGRES_DB: strapi
POSTGRES_USER: strapi
POSTGRES_PASSWORD: strapi
add user: 1000:1000 to postgres service, run docker-compose build and then docker-compose up.
Container running with correct write and read permissions for the defined user

Docker-Compose build fails [Permission Denied] with postgresql unless it uses a cached Dockerfile

Thanks for taking the time to read this post!
I'm currently building an application that makes use of Python, Flask, Docker, Docker-compose and Postgres on Ubuntu 18.04 LTS. Previously, docker-compose build would succeed and everything was working according to plan. However, now that I switched to another Dockerfile, and I'm not using the cached version of the previous Dockerfile anymore, the build breaks with the following error:
PermissionError: [Errno 13] Permission denied: '/usr/lib/python3.7/__pycache__/__future__.cpython-37.pyc.140409285875056'
dpkg: error processing package python3.7-minimal (--configure):
installed python3.7-minimal package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
python3.7-minimal
I have tried the following (Stackoverflow) posts:
"PermissionError: [Errno 13] Permission denied: '/usr/lib/python3.5/site-packages'" installing Django
docker-compose , PermissionError: [Errno 13] Permission denied: '/manage.py'
How to change permissions for a folder and its subfolders/files in one step?
pip install failing with: OSError: [Errno 13] Permission denied on directory
docker-compose up && docker-compose build : error with PostgreSQL
https://phoenixnap.com/kb/fix-sub-process-usr-bin-dpkg-returned-error-code-1
but alas, to no avail.
I'm using the following files:
Dockerfile.prod
# pull official base image
FROM python:3.9.0-slim-buster
# set working directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV FLASK_ENV production
ENV APP_SETTINGS src.config.ProductionConfig
# install system dependencies
RUN apt-get update \
&& apt-get -y install netcat gcc postgresql\
&& apt-get clean
# add and install requirements
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# add app
COPY . .
# add and run as non-root user
RUN adduser --disabled-password myuser
USER myuser
# run gunicorn
CMD gunicorn --bind 0.0.0.0:$PORT manage:app
docker-compose.yml
version: '3.8'
services:
api:
build:
context: .
dockerfile: Dockerfile.prod
entrypoint: ['/usr/src/app/entrypoint.sh']
volumes:
- .:/user/src/app
ports:
- 5004:5000
environment:
- FLASK_ENV=development
- APP_SETTINGS=src.config.DevelopmentConfig
- DATABASE_URL=postgresql://postgres:postgres#api-db:5432/api_dev
- DATABASE_TEST_URL=postgresql://postgres:postgres#api-db:5432/api_test
depends_on:
- api-db
api-db:
build:
context: ./src/db
dockerfile: Dockerfile
expose:
- 5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
./src/db/Dockerfile
FROM postgres:13-alpine
ADD create.sql /docker-entrypoint-initdb.d
Thanks once again for taking the time to read through this question, and if any additional information is required (e.g. a minimum viable Flask program to reproduce) please let me know!
Make sure docker belongs to your user groups:
$ groups
$ foo adm cdrom sudo dip plugdev lpadmin lxd sambashare docker
If that's not the case, try to create a docker group:
$ sudo groupadd docker
You might receive the message: groupadd: group 'docker' already exists
Cool, now add your user to the docker group:
$ sudo usermod -aG docker $USER
Check if docker belongs to your user group:
$ groups
$ docker adm cdrom sudo dip plugdev lpadmin lxd sambashare foo
You most likely need to logout and login back again.
Even if after that docker is not listed among the groups your user belongs to try:
$ newgrp docker
How to Fix Docker Permission Denied Error on Ubuntu

Running chown in Dockerfile does nothing

I'm having some trouble setting up a Nuxt and Rails container using Docker. The two containers are separate, but interact with each other.
Currently, I'm having trouble running the dev servers for both the Nuxt and the Rails containers due to insufficient permissions. Looking at the logs for both of the containers, it seems that Docker can't do actions such as mkdir.
EACCESS: Permission Denied: 'mkdir: /usr/src/app/.nuxt' # nuxt
EACCESS: Permission Denied: 'mkdir: /usr/src/app/tmp' # rails
My docker-compose.dev.yml file
version: 3
services:
backend:
privileged: true
image: tablevibes-backend
build:
dockerfile: Dockerfile-dev
context: tablevibes-backend
args:
UID: ${UID:-1001}
BUNDLER_VERSION: 2.0.2
PG_MAJOR: 10
mode: development
tty: true
stdin_open: true
volumes:
- ./tablevibes-backend:/usr/src/app:Z
- gem_data_api:/usr/local/bundle:cached
ports:
- "3000:3000"
depends_on:
- db
user: rails
client-ui:
image: client-ui
command: yarn run dev
build:
context: client-ui
dockerfile: Dockerfile-dev
args:
UID: ${UID:-1001}
PORT: 5000
MODE: DEV
restart: always
volumes:
- ./client-ui:/usr/src/app
- client_ui_node_modules:/usr/src/app/node_modules:cached
ports:
- 5000:5000
user: client-ui
The 2 Dockerfiles
The Rails Dockerfile-dev
FROM ruby:2.6.3
ARG PG_MAJOR
ARG BUNDLER_VERSION
ARG UID
ARG MODE
RUN adduser rails --uid $UID --disabled-password --gecos ""
# Add POSTGRESQL to the source list using the right version
RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo 'deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list
ENV RAILS_ENV $MODE
RUN apt-get update -qq && apt-get install -y postgresql-client-$PG_MAJOR vim
RUN apt-get -y install sudo
WORKDIR /usr/src/app
CMD chown -R rails /usr/src/app
COPY Gemfile /usr/src/app/Gemfile
COPY Gemfile.lock /usr/src/app/Gemfile.lock
ENV BUNDLER_VERSION $BUNDLER_VERSION
RUN gem install bundler:$BUNDLER_VERSION
RUN bundle install
COPY . /usr/src/app
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
The Nuxt Dockerfile-dev
FROM node:10
ARG UID
ARG MODE=DEV
ARG PORT
RUN adduser client-ui --uid $UID --disabled-password --gecos ""
RUN apt-get update
RUN apt-get -y install sudo
RUN mkdir /usr/src/app
RUN chown -R client-ui /usr/src/app
COPY package.json yarn.lock /usr/src/app
RUN yarn install
COPY . /usr/src/app
ENV API_URL=http://localhost:3000/v1
ENV REVIEW_URL=http://localhost:8000
# expose 5000 on container
EXPOSE $PORT
# set app serving to permissive / assigned
ENV NUXT_HOST=0.0.0.0
# set app port
ENV NUXT_PORT=$PORT
My problem is that those lines where I do RUN chown ... never seem to take place. If I manually go into the containers with docker exec -u root -it backend bash and run chown -R rails . manually, everything works as expected. Likewise I tried running chmod 777 as a test, however that also had no effect on the permission denied error I keep getting.
What might be causing Docker to ignore my chown command?
This Stack Overflow question seems relevant, however it doesn't quite apply because I don't have any VOLUME mounts inside my Dockerfiles. A user in the comments of the accepted answer has my same issue, though unfortunately no solution.
Containers are like ogres, or onions, they have layers.
When using VOLUMEs or MOUNTs, the directory (or file) is not actually IN the container, but only appears to be in it.
Your Dockerfile uses a layer for /usr/src/app, which as you probably already know is your ./tablevibes-backend directory on your host computer.
services:
backend:
volumes:
- ./tablevibes-backend:/usr/src/app:Z
When you use a volume or mount in this way, the only thing Docker can do is simple CRUD (create, read, update, delete) options, it can not (and should not) modify the metadata as it is modifying your host drive, which could be a security issue.
try this:
sudo chown -R $USER:$USER .

Docker - Permission denied while trying to access folder created in Dockerfile

I have problem with my Dockerfile (code below)
FROM node:4.2.6
MAINTAINER kamil
RUN useradd -ms /bin/bash node
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY /myFolder .
USER node
COPY --chown=node:node . .
RUN ["chmod", "777", "/home/node/app"]
ENTRYPOINT /home/node/app
CMD ["node myApp.js"]
I'm building docker image with
"docker build -t my_docker_image ."
and it finished with no errors.
Next I am running it with command "docker run --name my_run_docker_image -d my_docker_image" and its also finished without errors, but when I want to check status of my new container with "docker ps -l" command i'm getting info that status of my container is "EXITED".
Hence i'm trying to run it once again with command "docker start -a my_run_docker_image" but I'm receiving error:
"node MyApp.js: 1: node myApp.js: /home/node/app: Permission denied"
I was trying to run it with root user, without specified user but every time I have the same issue.
It looks like you may have a problem with your user add command.
Change
RUN useradd -ms /bin/bash/node
to
RUN useradd -ms /bin/bash node
And also
RUN mkdir -p /home/node/app && -R node:node /home/node/app
Needs to change to
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
The ENTRYPOINT and CMD tell Docker what command to run when you start the container. Since ENTRYPOINT is a bare string, it’s wrapped in a shell, and CMD is ignored. So when you start your container, the main container process is
/bin/sh -c '/home/node/app'
Which fails, because that is a directory.
In this Dockerfile, broadly, I’d suggest two things. The first is to install your application as root but then run it as non-root, as protection against accidentally overwriting the application code. The second is to prefer CMD to ENTRYPOINT in most cases, unless you’re clear on how they interact. You might come up with something more like:
FROM node:4.2.6
MAINTAINER kamil
WORKDIR /app # Docker will create on first use
COPY myFolder .
RUN useradd node # its shell should never matter
USER node
CMD ["node", "myApp.js"]

Docker cannot run on build when running container with a different user

I don't know the specifics why the node application does not run. Basically I added a dockerfile in a nodejs app, and here is my Dockerfile
FROM node:0.10-onbuild
RUN mv /usr/src/app /ghost && useradd ghost --home /ghost && \
cd /ghost
ENV NODE_ENV production
VOLUME ["/ghost/content"]
WORKDIR /ghost
EXPOSE 2368
CMD ["bash", "start.bash"]
Where start.bash looks like this:
#!/bin/bash
GHOST="/ghost"
chown -R ghost:ghost /ghost
su ghost << EOF
cd "$GHOST"
NODE_ENV={$NODE_ENV:-production} npm start
EOF
I usually run docker like so:
docker run --name ghost -d -p 80:2368 user/ghost
With that I cannot see what is going on, and I decided to run it like this:
docker run --name ghost -it -p 80:2368 user/ghost
And I got this output:
> ghost#0.5.2 start /ghost
> node index
Seems, like starting, but as I check the status of the container docker ps -a , it is stopped.
Here is the repo for that but, the start.bash and dockerfile is different, because I haven't committed the latest, since both are not working:
JoeyHipolito/Ghost
I manage to make it work, there is no error in the start bash file nor in the Dockerfile, it's just that I failed to build the image again.
With that said, you can checkout the final Dockerfile and start.bash file in my repository:
Ghost-blog__Docker (https://github.com/joeyhipolito/ghost)
At the time I write this answer, you can see it in the feature-branch, feature/dockerize.

Resources