I have a script which must be run as a non-root. This script also creates directories and files. If I run the script as a non-root user in docker, I get a permission denied error creating dirs. I tried to chmod the parent directory the script is in but it doesn't work. What should be the best practice here?
RUN mkdir test
WORKDIR /test
USER testuser
RUN mkdir .cache <--- permission denied
That happens because your /test directory was created by root, and by default won't allow any other users to create anything in it. To change ownership to the user you want, you can use chown before your USER testuser step:
RUN chown testuser /test
If there are already files inside the directory, you will need to pass the -R flag to change the permission recursively:
RUN chown -R testuser /test
Another option would be giving the directory red+write+execute permissions for all users. However, this is probably NOT what you want, the above should serve you well for almost all cases.
RUN chmod 777 /test
Related
Created an application image on top of ubuntu. The application requires a non-root user.
I am able to create the image and get it working but the RUN statement for creating new user significantly increases the size of this image.
Dockerfile snippet:
## create newuser and give correct permissions to home directory
RUN useradd newuser --create-home --shell /bin/bash && \
echo 'newuser:newpassword' | chpasswd && \
chown -R newuser:newuser /home/newuser && \
chmod 755 /home/newuser
USER newuser
WORKDIR /home/newuser
Is there a better way to create a new user?
Thinking about alternate approaches, wonder if one uses multi-stage build to create this new user and then use copy --from to get relevant files in the final build. Not sure what those files would be.
Don't chown the directory; leave root owning it. You also shouldn't need to set a shell, or a password, or create a home directory; none of these things will be used in normal operation.
I'd suggest creating the user towards the start of the Dockerfile (it is fairly fixed and so this step can be cached) but only switching USER at the very end of the file, when you're setting up the metadata for how to run the container.
A Node-based example:
FROM node:lts # debian-based
# Create the non-root user up front
RUN adduser --system --group --no-create-home newuser
# Copy and build the package as usual
WORKDIR /app
COPY package.json yarn.lock .
RUN yarn install
COPY . .
RUN yarn build
# Now the application is built
# And root owns all the files
# And that's fine
# Say how to run the container
EXPOSE 3000
USER newuser
CMD yarn start
Having root owning the files gives you a little extra protection in case something goes wrong. If there's a bug that allows files in the container to be overwritten, having a different user owning those files prevents the application code or static assets from being inadvertently modified.
If your application needs to read or write files then you could create a specific directory for that:
# Towards the end of the file, but before the USER
RUN mkdir data && chown newuser data
This will let the operator mount some storage over the otherwise-empty directory. This is the only thing that has the newly created user ID in it at all, so if the storage comes with its own owner it shouldn't be an operational problem; you need to also specify the matching user ID at container startup time.
docker run -u $(id -u) -v $PWD/data:/app/data ...
Seems like a basic issue but couldnt find any answers so far ..
When using ADD / COPY in Dockerfile and running the image on linux, the default file permission of the file copied in the image is 644. The onwner of this file seems to be as 'root'
However, when running the image, a non-root user starts the container and any file thus copied with 644 permission cannot execute this copied/added file and if the file is executed at ENTRYPOINT it fails to start with permission denied error.
I read in one of the posts that COPY/ADD after Docker 1.17.0+ allows chown but in my case i dont know who will be the non-root user starting so i cannot set the permission as that user.
I also saw another work around to ADD/COPY files to a different location and use RUN to copy them from the temp location to actual folder like what am doing below. But this approach doesnt work as the final image doesnt have the files in /otp/scm
#Installing Bitbucket and setting variables
WORKDIR /tmp
ADD atlassian-bitbucket-${BITBUCKET_VERSION}.tar.gz .
COPY bbconfigupdater.sh .
#Copying Entrypoint script which will get executed when container starts
WORKDIR /tmp
COPY entrypoint.sh .
RUN ls -lrth /tmp
WORKDIR /opt/scm
RUN pwd && cp /tmp/bbconfigupdater.sh /opt/scm \
&& cp /tmp/entrypoint.sh /opt/scm \
&& cp -r /tmp/atlassian-bitbucket-${BITBUCKET_VERSION} /opt/scm \
&& chgrp -R 0 /opt/ \
&& chmod -R 755 /opt/ \
&& chgrp -R 0 /scm/bitbucket \
&& chmod -R 755 /scm/bitbucket \
&& ls -lrth /opt/scm && ls -lrth /scmdata
Any help is appreciated to figure out how i can get my entrypoint script copied to the desired path with execute permissions set.
The default file permission is whatever the file permission is in your build context from where you copy the file. If you control the source, then it's best to fix the permissions there to avoid a copy-on-write operation. Otherwise, if you cannot guarantee the system building the image will have the execute bit set on the files, a chmod after the copy operation will fix the permission. E.g.
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
A better option with newer versions of docker (and which didn't exist when this answer was first posted) is to use the --chmod flag (the permissions must be specified in octal at last check):
COPY --chmod=0755 entrypoint.sh .
You do not need to know who will run the container. The user inside the container is typically configured by the image creator (using USER) and doesn't depend on the user running the container from the docker host. When the user runs the container, they send a request to the docker API which does not track the calling user id.
The only time I've seen the host user matter is if you have a host volume and want to avoid permission issues. If that's your scenario, I often start the entrypoint as root, run a script called fix-perms to align the container uid with the host volume uid, and then run gosu to switch from root back to the container user.
A --chmod flag was added to ADD and COPY instructions in Docker CE 20.10. So you can now do.
COPY --chmod=0755 entrypoint.sh .
To be able to use it you need to enable BuildKit.
# enable buildkit for docker
DOCKER_BUILDKIT=1
# enable buildkit for docker-compose
COMPOSE_DOCKER_CLI_BUILD=1
Note: It seems to not be documented at this time, see this issue.
Im trying to create dir in docker file and I got error during the build
FROM circleci/openjdk:8-jdk-browsers
#RUN chown newuser /dep
#USER newuser
RUN mkdir /dep
The error is:
mkdir: cannot create directory ‘/dep’: Permission denied`
The command `/bin/sh -c mkdir -p /dep` returned a non-zero code: 1
even if I try only dep .
I try to use chown without success, any idea ?
This image is run with the user circleci, you can check this by adding a whoami to a RUN statement in your Dockerfile. This user has no permission to create folders in /. So, you can either create a folder somewhere where this user has the necessary rights (e.g. /home/circleci/dep), or you just go with sudo mkdir.
I have Dockerfile as shown here.
A script in the entrypoint creates a directory and places few artifacts.
# from base image
FROM ......
RUN mkdir -p /home/myuser
RUN groupadd -g 999 myuser &&\
useradd -r -u 999 -g myuser myuser
ENV HOME=/home/myuser
ENV APP_HOME=/home/myuser/workspace
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
RUN chown -R myuser:myuser $APP_HOME
USER myuser
ENTRYPOINT ......
I start a container for the above image as shown here
sudo docker run -v ${WORKSPACE}/output:/home/myuser/workspace/output image
I could not get the artifacts in the host machine. ${WORKSPACE}/output created with permission drwxr_xr_x
What is the process to get the container files into the host machine?
Additional Info:
My host username is kit
container user is myuser
container works perfectly fine - at the time of creating output file it throws an error that Permission denied
I tried to give full permission drwxrwxrwx to ${WORKSPACE}/output. then i could see the output files.
The permission denied error is because you are running a container with uid 999, but trying to write to a host directory that is owned by uid 1000 and only configured to allow writes by the user. You can:
chmod the directory to allow anyone to write (not recommended, but quick and easy)
update your image to match the uid/gid of your user on the host
switch to using a named volume
use an entrypoint to align the container uid/gid to that of a volume mount before starting your app
I go into a bit more detail on these in my slides here. There are also some speaker notes in there (I believe either P or S will bring them up).
I'm trying to write a Dockerfile file to run Pydio community edition. I've an almost working Dockerfile.
RUN mv pydio-core-${PYDIO_VERSION} /var/www/pydio-core
RUN chmod -R 770 /var/www/pydio-core
RUN chmod -R 777 /var/www/pydio-core/data/files/ /var/www/pydio-core/data/personal/
RUN chown -R www-data:www-data /var/www/pydio-core
VOLUME /var/www/pydio-core/data/files
VOLUME /var/www/pydio-core/data/personal
This works except that when the container is started for the first time, the access rights of the files and personal folders is 755 and their owner is not www-data but 1000. So once started, I must connect the container to fix permissions (770) and ownership (www-data) and everything works.
I just wonder if it may have something in my Dockerfile which could explain the problem, or if the issue probably comes from the Pydio source code itself.