Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share files between host system and docker container using specific UID

Tags:

docker

I'm trying to share files within a Docker guest using the volume sharing. In order to get the same UID, and therefore interoperability with those files, I would like to create a user in the Docker guest with the same UID as my own user.

In order to test out the idea, I wrote the following simplistic Dockerfile:

FROM phusion/baseimage

RUN touch /root/uid-$UID

Testing it with docker build -t=docktest . and then docker run docktest ls -al /root reveals that the file is simply named uid-.

Is there a means to share host environment variables with Docker during the guest build process?

like image 707
alkalinity Avatar asked Jan 13 '15 14:01

alkalinity


4 Answers

While researching a solution to this problem, I have found the following article to be a great resource: https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

In my scripts, the solution boiled down to the following :

docker run --user $(id -u):$(id -g) -v /hostdirectory:/containerdirectory -v /etc/passwd:/etc/passwd myimage

Of course, id -u can be replaced by other means of retrieving a user's gid, such as stat -c "%u" /somepath

like image 148
Dalzhim Avatar answered Nov 16 '22 00:11

Dalzhim


The environment is not shared, you could use -e, --env options to set env variables in container.

I usually use this approach when I want to have the same owner of the mapped volume: I check uid & gid of directory in container and then create a corresponding user. Here my script (setuser.sh) which creates a user for a directory:

#!/bin/bash

setuser() {
  if [ -z "$1" ]; then
    echo "Usage: $0 <path>"
    return
  fi
  CURRENT_UID=`id -u`
  DEST_UID=`stat -c "%u" $1`
  if [ $CURRENT_UID = $DEST_UID ]; then
    return
  fi
  DEST_GID=`stat -c "%g" $1`
  if [ -e /home/$DEST_UID ]; then
    return
  fi
  groupadd -g $DEST_GID $DEST_GID
  useradd -u $DEST_UID -g $DEST_GID $DEST_UID
  mkdir -p /home/$DEST_UID
  chown $DEST_UID:$DEST_GID /home/$DEST_UID
}
setuser $1

And this is the wrapper script which runs commands as the user, where the directory with permissions is specified either as $USER_DIR or in /etc/user_dir

#!/bin/bash
if [ -z "$USER_DIR" ]; then
  if [ -e /etc/user_dir ]; then
    export USER_DIR=`head -n 1 /etc/user_dir`
  fi
fi
if [ -n "$USER_DIR" ]; then
  if [ ! -d "$USER_DIR" ]; then
    echo "Please mount $USER_DIR before running this script"
    exit 1
  fi
  . `dirname $BASH_SOURCE`/setuser.sh $USER_DIR
fi
if [ -n "$USER_DIR" ]; then
  cd $USER_DIR
fi
if [ -e /etc/user_script ]; then
  . /etc/user_script
fi
if [ $CURRENT_UID = $DEST_UID ]; then
  "$@"
else
  su $DEST_UID -p -c "$@"
fi

P.S. Alleo suggested different approach: to map users and groups files into container and to specify uid and gid. So your container does not depend on built-in users/groups you could use it without additional scripts.

like image 44
ISanych Avatar answered Nov 16 '22 01:11

ISanych


This is not possible and will probably never be possible because of the design philosophy of keeping builds independent of machines. Issue 6822.

like image 39
Usman Ismail Avatar answered Nov 16 '22 01:11

Usman Ismail


I slightly modified @ISanych answer:

#!/usr/bin/env bash

user_exists() {
  id -u $1 > /dev/null 2>&1
}

group_exists() {
  id -g $1 > /dev/null 2>&1
}

setuser() {
  if [[ "$#" != 3 ]]; then
    echo "Usage: $0 <path> <user> <group>"
    return
  fi
  local dest_uid=$(stat -c "%u" $1)
  local dest_gid=$(stat -c "%g" $1)
  if user_exists $dest_uid; then
    id -nu $dest_uid
    return
  fi
  local dest_user=$2
  local dest_group=$3

  if user_exists $dest_user; then
    userdel $dest_user
  fi

  if group_exists $dest_group; then
    groupdel $dest_user
  fi

  groupadd -g $dest_gid $dest_group
  useradd -u $dest_uid -g $dest_gid -s $DEFAULT_SHELL -d $DEFAULT_HOME -G root $dest_user
  chown -R $dest_uid:$dest_gid $DEFAULT_HOME
  id -nu $dest_user
}

REAL_USER=$(setuser $SRC_DIR $DEFAULT_USER $DEFAULT_GROUP)

setuser function accepts user and group names that you want to assign to uid and gid of provided directory. Then if user with such uid exists then it simply returns login corresponding to this uid, otherwise it creates user and group and returns login originally passed to function.

So you get the login of user that owns destination directory.

like image 42
mixel Avatar answered Nov 16 '22 00:11

mixel