Crossplatform way to set user and group ids for shared volumes
As already mentioned by @nils in #2, we need a way to set the user and group id for shared volumes in a crossplatform way.
As the user and group ids on macOS does not align with the ids given under Linux, which start at 1000
, we needed the following workaround.
Note: Nobody tested this under Windows
In the past we had two cases. For both cases we need to create a little shell script, that wraps the docker-compose
command:
docker-compose wrapper script
We create a docker-compose
wrapper script which exports the hosts user id and group id:
docker-compose.sh:
# export current UID and GID
export DUID="$(/usr/bin/id -u)"
export DGID="$(/usr/bin/id -g)"
docker-compose "$@"
The docker-compose.yml passes both variables to the image:
docker-compose.yml:
version: '3'
services:
someservice:
build:
args:
# We want to use our DUID & DGID , so that root is not
# the owner of some newly created files.
DUID: ${DUID:-1000}
DGID: ${DGID:-1000}
volumes:
- ./someservice:/srv/app
ports:
- 8000:8000
Case 1: Manually creating the user of the application
The user, under which the main process of the container is running, is created manually at build-time of the image.
In the corresponding Dockerfile, we create a group app
and a user app
and assign the hosts user (= the developers) user-id and group-id to both:
Dockerfile:
# -- 8< --- *snipp* --- 8< --
ARG DUID=1000
ARG DGID=1000
ARG APP_GROUP="app"
ARG APP_USER="app"
RUN mkdir -p /srv/app
RUN \
# check if there is already a group with the provided DGID and store its name
EXISTING_GROUP=`sed -n "s/^\([a-zA-Z0-9-]\{1,\}\):x:$DGID:.*$/\1/p" /etc/group` \
# if there is no group then create one, else store the groups name in the APP_GROUP variable
&& if [ -z $EXISTING_GROUP ]; then addgroup -S $APP_GROUP -g $DGID; else APP_GROUP=$EXISTING_GROUP; fi \
# add the APP_USER and put her / him into the APP_GROUP
&& adduser -S $APP_USER -G $APP_GROUP -u $DUID
WORKDIR /srv/app
USER app
# -- 8< --- *snipp* --- 8< --
When the group-id of the host is already defined in /etc/group
, then the existing group is assigned to the user, otherwise the user is assigned to the new group.
2. Using an existing user for the application
Some images already define a user, under which all subsequent commands will run (eg. all node
-images). Here we just assign the hosts user (= the developers) user-id and group-id to the existing groups:
# -- 8< --- *snipp* --- 8< --
ARG DUID=1000
ARG DGID=1000
RUN \
# change the group-id of the node group the the developers group-id, even when this group-id already exists (-o)
&& groupmod -o -g $DGID node \
# change the UID and the primary group of the node user to the developers user-id and group-id
&& usermod -u $DUID -g $DGID node
USER node
# -- 8< --- *snipp* --- 8< --
The clue here is to allow the assignment of the group-id, even when a group with that id already exists.