Many companies with dedicated security team, requires the UID user used by docker images greater than 1000 to avoid conflict with host id. By default, Linux will assign 1000 UID for the first non-root non-system user account.
For docker images that use ENTRYPOINT
we need to use the command
# command is command line that available on docker image docker run --entrypoint COMMAND IMAGE # example docker run --entrypoint id quay.io/keycloak/keycloak:21.1.1
for CMD
docker run IMAGE COMMAND # example docker run debian id
Playing with Docker Image
To test some commands or some cases we don’t need to build a new image every time, instead, we access the image/container shell account using root or any other user.
docker run -u root --entrypoint bash quay.io/keycloak/keycloak:21.1.1 docker run -it -u root debian bash
Building a docker image takes time, so this command saves a lot of time. But remember changes in the shell are only temporary, when you exit the terminal all changes are gone, so keep notes about that.
To verify the current user id use id
, lets’s use Keycloak for our example.
$ docker run --entrypoint id quay.io/keycloak/keycloak:21.1.1 uid=1000(keycloak) gid=0(root) groups=0(root)
Let’s say we’ll update the user to 10000 UID, first thing to do is check the Linux distro and usermod
command line, which is useful to manipulate users and groups in Linux.
> docker run -it --entrypoint bash quay.io/keycloak/keycloak:21.1.1 bash-5.1$ cat /etc/*release NAME="Red Hat Enterprise Linux" VERSION="9.1 (Plow)" ID="rhel" ID_LIKE="fedora" VERSION_ID="9.1" PLATFORM_ID="platform:el9" PRETTY_NAME="Red Hat Enterprise Linux 9.1 (Plow)" ANSI_COLOR="0;31" LOGO="fedora-logo-icon" CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" HOME_URL="https://www.redhat.com/" DOCUMENTATION_URL="https://access.redhat.com/documentation/red_hat_enterprise_linux/9/" BUG_REPORT_URL="https://bugzilla.redhat.com/" REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" REDHAT_BUGZILLA_PRODUCT_VERSION=9.1 REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" REDHAT_SUPPORT_PRODUCT_VERSION="9.1" Red Hat Enterprise Linux release 9.1 (Plow) Red Hat Enterprise Linux release 9.1 (Plow) bash-5.1$ usermod bash: usermod: command not found
From that information we know, Keycloak uses RHEL 9.1, and usermod is not available. Then our other option is to update the UID in /etc/passwd
using sed
(sed -i 's/1000/10000/g' /etc/passwd
). To make the changes permanent, we need to build a new docker image based on the Keycloak docker image.
Create a new folder keycloak-custom-user
, add Docker with following lines
FROM quay.io/keycloak/keycloak:21.1.1 USER root RUN sed -i 's/1000/10000/g' /etc/passwd USER 10000
then build the docker image
cd keycloak-custom-user docker build . -t keycloak:21.1.1-atetux1
if you notice from the build command above, I add atetux1 at the end of the docker tag version, the reason was so we understand which base image we use, and atetux1 is the indicator that updates once, hence the number 1.
After the new build is done, check the user UID
$ docker run --entrypoint id keycloak:21.1.1-atetux1 uid=10000(keycloak) gid=0(root) groups=0(root)
then run the docker image to make sure it’s working properly. This command is specific for Keycloak
docker run keycloak:21.1.1-atetux1 start-dev
Update UID/GID using usermod groupmod
Let’s take Superset as another example, instead of using some random image we prefer using real-life applications that use by many people and in production.
> docker run apache/superset id uid=1000(superset) gid=1000(superset) groups=1000(superset)
It uses UID 1000 and GID 1000, if we check the image has usermod and groupmod
which usermod groupmod
Create another folder superset-custom-user
, create a Dockerfile with following contents
FROM apache/superset USER root RUN usermod -u 10000 superset && groupmod -g 10000 superset USER 10000
let’s build the image
cd superset-custom-user docker build . -t superset:atetux1
then check the UID and GID in our new image
$ docker run superset:atetux1 id uid=10000(superset) gid=10000(superset) groups=10000(superset)
We intentionally use apache/superset
without any tag, to let the user aware that not the proper and recommended way to use the docker image, always stick to a certain tag, for example, apache/superset:2.1.0