58

Similar to the SO post about replicating UID/GID in container from host but how do you build the image with a user with replicate UID and GID? Preferably, how do you do it with a dockerfile?

I can do it with a bash script:

#!/bin/bash

# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`

# create bb.dockerfile:
cat << EOF1 > bb.dockerfile
 FROM ubuntu:xenial-20170214
 ARG UNAME=testuser
EOF1

 echo ARG UID=${curr_uid} >> bb.dockerfile
 echo ARG GID=${curr_gid} >> bb.dockerfile

cat << EOF2 >> bb.dockerfile
 RUN groupadd -g \$GID \$UNAME
 RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
 USER \$UNAME
 CMD /bin/bash
EOF2

docker build -f bb.dockerfile -t testimg .

This bash will generate a docker file as the following and build on it.

 FROM ubuntu:xenial-20170214
 ARG UNAME=testuser
 ARG UID=1982
 ARG GID=1982
 RUN groupadd -g $GID $UNAME
 RUN useradd -m -u $UID -g $GID -s /bin/bash $UNAME
 USER $UNAME
 CMD /bin/bash

What I'm asking for, is to remove the hardcoded host UID 1982 and GID 1982 from the dockerfile.

minghua
  • 5,981
  • 6
  • 45
  • 71

2 Answers2

105

You can pass it as a build arg. Your Dockerfile can be static:

FROM ubuntu:xenial-20170214
ARG UNAME=testuser
ARG UID=1000
ARG GID=1000
RUN groupadd -g $GID -o $UNAME
RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME
USER $UNAME
CMD /bin/bash

Then you'd pass the options on your build command:

docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) \
  -f bb.dockerfile -t testimg .

Note that I've solved similar problems to this a different way, by running an entrypoint as root that looks a file/directory permissions of the host volume mount, and adjust the uid/gid of the users inside the container to match the volume uid/gid. After making that change, it drops access from the root user to the modified uid/gid user and runs the original command/entrypoint. The result is the image can be run unchanged on any developer machine. An example of this can be found in my jenkins-docker repo:

https://github.com/sudo-bmitch/jenkins-docker

BMitch
  • 231,797
  • 42
  • 475
  • 450
  • 6
    I don't understand, do the UID and GID args at the command line shadow/override the "static" Dockerfile entries? – Alexander Mills May 16 '18 at 16:57
  • Inside my docker container ubuntu guest, gid 20 belongs to dialout. Usually your user account on the host should be assigned its own group id, not to reuse the 20. Do you get 20 if you run `id -g`? What do you get by `id -u`? – minghua May 16 '18 at 17:06
  • 1
    @AlexanderMills I'm guessing you're maybe running on macos where guid 20 = staff, but the guest is some linux where 20 = something else. This idea of passing the group ID and creating the group only seems to make sense if the group doesn't already exist, which would be the case on linux hosts, where conventionally your GID would be a group containing only yourself. – Hakanai Oct 08 '18 at 02:55
  • 3
    @AlexanderMills yes, default values for docker args in the dockerfile get overridden by the build command. If the uid/gid already exist inside the container, you can add a `-o` option to allow non-unique id's. – BMitch Oct 08 '18 at 12:25
  • clean answer & it solves lot of problems with docker. Especially while using jenkins to spin up docker.. – harshavmb Jun 23 '20 at 08:18
  • What if the gid changes from the system where the container is built to the one it is run on? – Raketenolli Sep 18 '20 at 09:17
  • @Raketenolli that's where the second option is more appropriate and the reason I created it. – BMitch Sep 18 '20 at 12:54
  • Same problem as @AlexanderMills. How do compose entries overwrite the build args at runtime? – andig Oct 19 '22 at 15:51
  • @BMitch thanks for sharing that example, it's very interesting! – liiight Jul 07 '23 at 16:01
0

Eventually the bb.bash looks like:

#!/bin/bash

# current uid and gid
curr_uid=`id -u`
curr_gid=`id -g`

# create bb.dockerfile:
cat << EOF2 > bb.dockerfile
 FROM ubuntu:xenial-20180417
 ARG UNAME=testuser
 ARG UID=1000
 ARG GID=1000
 RUN groupadd -g \$GID \$UNAME
 RUN useradd -m -u \$UID -g \$GID -s /bin/bash \$UNAME
 USER \$UNAME
 CMD /bin/bash
EOF2    

docker build --build-arg UID=${curr_uid} --build-arg GID=${curr_gid} \
    -f bb.dockerfile -t testimg .

Then another script is to create the container:

#!/bin/bash

docker run -it -d -v $(pwd)/shared:/home/testuser/shared \
    --name testcontainer -P testimg
minghua
  • 5,981
  • 6
  • 45
  • 71
  • Also created a docker file and script to run X over ssh: see [superuser SO "Run JetPack TX2 Installer in a Docker Container"](https://superuser.com/a/1323124). – minghua May 16 '18 at 18:01