given that $USERNAME is set to 'ros', I woiuld like to create a user called ros, with a home directory, home/ros, with sudo privs and no password.
RUN adduser --ingroup sudo --disabled-password --gecos "" --shell /bin/bash --home /home/$USERNAME $USERNAME
Does that not do it?
Docker is simple, it just runs the commands you give it against the image base you start with. That one line is making a bunch of assumptions that may or may not be true:
adduser is installed
sudo is installed
/etc/sudoers is configured to allow root permissions for users in the sudo group
/bin/bash is installed
You've already created /home
You've already created /home/$USERNAME
If all those assumptions are true before that RUN line, then it may work, but of course, there may be another assumption I'm overlooking.
Related
My Dockerfile extends from php:8.1-apache. The following happens while developing:
The application creates log files (as www-data, 33:33)
I create files (as the image's default user root, 0:0) within the container
These files are mounted on my host where I'm acting as user (1000:1000). Of course I'm running into file permission issues now. I'd like to update/delete files created in the container on my host and vice versa.
My current solution is to set the image's user to www-data. In that way, all created files belong to it. Then, I change its user and group id from 33 to 1000. That solves my file permission issues.
However, this leads to another problem:
I'm prepending sudo -E to the entrypoint and command. I'm doing that because they're normally running as root and my custom entrypoint requires root permissions. But in that way the stop signal stops working and the container has to be killed when I want it to stop:
~$ time docker-compose down
Stopping test_app ... done
Removing test_app ... done
Removing network test_default
real 0m10,645s
user 0m0,167s
sys 0m0,004s
Here's my Dockerfile:
FROM php:8.1-apache AS base
FROM base AS dev
COPY entrypoint.dev.sh /usr/local/bin/custom-entrypoint.sh
ARG user_id=1000
ARG group_id=1000
RUN set -xe \
# Create a home directory for www-data
&& mkdir --parents /home/www-data \
&& chown --recursive www-data:www-data /home/www-data \
# Make www-data's user and group id match my host user's ones (1000 and 1000)
&& usermod --home /home/www-data --uid $user_id www-data \
&& groupmod --gid $group_id www-data \
# Add sudo and let www-data execute it without asking for a password
&& apt-get update \
&& apt-get install --yes --no-install-recommends sudo \
&& rm --recursive --force /var/lib/apt/lists/* \
&& echo "www-data ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/www-data
USER www-data
# Run entrypoint and command as sudo, as my entrypoint does some config substitution and both normally run as root
ENTRYPOINT [ "sudo", "-E", "custom-entrypoint.sh" ]
CMD [ "sudo", "-E", "apache2-foreground" ]
Here's my custom-entrypoint.sh
#!/bin/sh
set -e
sed --in-place 's#^RemoteIPTrustedProxy.*#RemoteIPTrustedProxy '"$REMOTEIP_TRUSTED_PROXY"'#' $APACHE_CONFDIR/conf-available/remoteip.conf
exec docker-php-entrypoint "$#"
What do I need to do to make the container catch the stop signal (it is SIGWINCH for the Apache server) again? Or is there a better way to handle the file permission issues, so I don't need to run the entrypoint and command with sudo -E?
What do I need to do to make the container catch the stop signal (it is SIGWINCH for the Apache server) again?
First, get rid of sudo, if you need to be root in your container, run it as root with USER root in your Dockerfile. There's little value add to sudo in the container since it should be an environment to run one app and not a multi-user general purpose Linux host.
Or is there a better way to handle the file permission issues, so I don't need to run the entrypoint and command with sudo -E?
The pattern I go with is to have developers launch the container as root, and have the entrypoint detect the uid/gid of the mounted volume, and adjust the uid/gid of the user in the container to match that id before running gosu to drop permissions and run as that user. I've included a lot of this logic in my base image example (note the fix-perms script that tweaks the uid/gid). Another example of that pattern is in my jenkins-docker image.
You'll still need to either configure root's login shell to automatically run gosu inside the container, or remember to always pass -u www-data when you exec into your image, but now that uid/gid will match your host.
This is primarily for development. In production, you probably don't want host volumes, use named volumes instead, or at least hardcode the uid/gid of the user in the image to match the desired id on the production hosts. That means the Dockerfile would still have USER www-data but the docker-compose.yml for developers would have user: root that doesn't exist in the compose file in production. You can find a bit more on this in my DockerCon 2019 talk (video here).
You can use user namespace to map different user/group in your docker to you on the host.
For example, the group www-data/33 in the container could be the group docker-www-data/100033 on the host, you just have be in the group to access log files.
Through the next cmd I am trying to clone into the /home/impdev/Impala folder. Yet, docker clones into the root/Impala folder. Is there a way to remedy this?
RUN adduser --disabled-password --gecos '' impdev && \
echo 'impdev ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
su - impdev && \
git clone https://gitbox.apache.org/repos/asf/impala.git ~/Impala
This is important for me as when you clone from an account ownership and group values are assigned to the cloned folder and its sub-folders.
You should use the Dockerfile USER and WORKDIR directives to control the current user context. This might look like
USER root
RUN adduser --disabled-password --gecos '' --no-create-home impdev
WORKDIR /impdev
USER impdev
RUN git clone https://gitbox.apache.org/repos/asf/impala.git
Remember that in many ways the Docker environment is different from a typical Linux environment: since an image generally only packages a single application and its immediate dependencies, it's not usually interesting to create multiple users or think about users as having home directories. You almost never use su or sudo since a container generally only does one thing and starts up as the user it needs to be to do it. Both commands are also difficult to use in scripts. (In your example, if you do su to the new user, it completes and returns to the original root-user context before the script moves on to the next command.)
I'm trying to deploy metricbeat on openshift, and after many hours of work i cannot have it worked.
The same image is running normally on docker.
Thank you
#Dockerfile
FROM docker.elastic.co/beats/metricbeat:7.2.0
COPY metricbeat.yml /usr/share/metricbeat/metricbeat.yml
USER root
RUN mkdir /var/log/metricbeat \
&& chown metricbeat /usr/share/metricbeat/metricbeat.yml \
&& chown metricbeat /usr/share/metricbeat/metricbeat \
&& chmod go-w /usr/share/metricbeat/metricbeat.yml \
&& chown metricbeat /var/log/metricbeat
COPY entrypoint.sh /usr/local/bin/custom-entrypoint
RUN chmod +x /usr/local/bin/custom-entrypoint \
&& chown metricbeat /usr/local/bin/custom-entrypoint
ENV PATH="/usr/share/metricbeat:${PATH}"
USER metricbeat
ENTRYPOINT [ "/usr/local/bin/custom-entrypoint" ]
#entrypoint.sh
#!/usr/bin/env bash
/usr/share/metricbeat/metricbeat -e --strict.perms=false -c /usr/share /metricbeat/metricbeat.yml
Error: /usr/local/bin/custom-entrypoint: line 2: /usr/share/metricbeat/metricbeat: Permission denied
The Dockerfile shows switching to the root user while setting up the directory structure and permissions when building the image, and finally switching to USER metricbeat to run the container with it.
However, by default OpenShift runs containers with a user with a random UID (from a preconfigured range).
One option is to relax the security policy as Graham Dumpleton suggested.
To make it work without relaxing the security, I'll suggest to change ownership as follows:
RUN chown -R metricbeat:root /usr/share/metricbeat \
&& chmod -R 0775 /usr/share/metricbeat
...or incorporate the above two commands in the first RUN instruction.
I am new with the docker and I am trying to do a simple setup, which the scope is:
create a home folder and give appropriate permissions
On host side:
I have a user called devel which I put into the docker group.
When I run 'groups devel' I get back the group docker. UID 1000 and GID 1000.
my subuid file:
devel:1000:1
devel:100000:65536
my subgid file:
devel:1000:1
devel:100000:65536
following a tutorial and setting the sysconfig file to start with that 'devel' as option for remapping.
I then created this Dockerfile:
USER root
RUN groupadd -g 1000 devel
#Create the user with home directory
RUN useradd -d /var/opt/devel -u 1000 -g 1000 --shell /bin/bash devel
#Just for being very-very-very-very sure:
RUN chown -vhR devel:devel /var/opt/devel
#test with ls
RUN ls -ltr /var/opt/
User deploy
#test again by creating a file:
RUN touch /var/opt/devel/TEST.txt
RUN ls -ltr /var/opt/devel/TEST.txt
USER root
RUN ls -ltr /var/opt
USER devel
CMD ["/bin/bash"]
The result is that the directory which is created has group "devel" but the user owner is always the root.
I have disabled after 12 hours checking why the SELINUX for another reason (the reason was that id did not let me to use chown at all) but now I am stack and I know what else magic do I need to do.
The docker version is 18.09.1-ol ( oracle linux 7)
Hope someone has an idea.
Thanks
I'm using alpine (or an image that is based on Alpine) as the base image in my Dockerfile. Which instructions do I need to add to create a user?
Eventually I'll use this user to run the application I'll place into the container so that the root user does not.
Alpine uses the command adduser and addgroup for creating users and groups (rather than useradd and usergroup).
FROM alpine:latest
# Create a group and user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Tell docker that all future commands should run as the appuser user
USER appuser
The flags for adduser are:
Usage: adduser [OPTIONS] USER [GROUP]
Create new user, or add USER to GROUP
-h DIR Home directory
-g GECOS GECOS field
-s SHELL Login shell
-G GRP Group
-S Create a system user
-D Don't assign a password
-H Don't create home directory
-u UID User id
-k SKEL Skeleton directory (/etc/skel)
Add new user official docs
The commands are adduser and addgroup.
Here's a template for Docker you can use in busybox environments (alpine) as well as Debian-based environments (Ubuntu, etc.):
ENV USER=docker
ENV UID=12345
ENV GID=23456
RUN adduser \
--disabled-password \
--gecos "" \
--home "$(pwd)" \
--ingroup "$USER" \
--no-create-home \
--uid "$UID" \
"$USER"
Note the following:
--disabled-password prevents prompt for a password
--gecos "" circumvents the prompt for "Full Name" etc. on Debian-based systems
--home "$(pwd)" sets the user's home to the WORKDIR. You may not want this.
--no-create-home prevents cruft getting copied into the directory from /etc/skel
The usage description for these applications is missing the long flags present in the code for adduser and addgroup.
The following long-form flags should work both in alpine as well as debian-derivatives:
adduser
BusyBox v1.28.4 (2018-05-30 10:45:57 UTC) multi-call binary.
Usage: adduser [OPTIONS] USER [GROUP]
Create new user, or add USER to GROUP
--home DIR Home directory
--gecos GECOS GECOS field
--shell SHELL Login shell
--ingroup GRP Group (by name)
--system Create a system user
--disabled-password Don't assign a password
--no-create-home Don't create home directory
--uid UID User id
One thing to note is that if --ingroup isn't set then the GID is assigned to match the UID. If the GID corresponding to the provided UID already exists adduser will fail.
addgroup
BusyBox v1.28.4 (2018-05-30 10:45:57 UTC) multi-call binary.
Usage: addgroup [-g GID] [-S] [USER] GROUP
Add a group or add a user to a group
--gid GID Group id
--system Create a system group
I discovered all of this while trying to write my own alternative to the fixuid project for running containers as the hosts UID/GID.
My entrypoint helper script can be found on GitHub.
The intent is to prepend that script as the first argument to ENTRYPOINT which should cause Docker to infer UID and GID from a relevant bind mount.
An environment variable "TEMPLATE" may be required to determine where the permissions should be inferred from.
(At the time of writing I don't have documentation for my script. It's still on the todo list!!)
There is package shadow that brings useradd & usermod.
adduser has some stupid limitations:
$ sudo adduser --disabled-password root
adduser: user 'root' in use
but usermod doesn't:
$ sudo apk add shadow
$ sudo usermod --unlock root