使用特定 UID 在主机系统和 docker 容器之间共享文件
Share files between host system and docker container using specific UID
我正在尝试使用卷共享在 Docker 来宾中共享文件。为了获得相同的 UID,并因此与这些文件进行互操作,我想在 Docker guest 中创建一个与我自己的用户具有相同 UID 的用户。
为了验证这个想法,我写了以下简单的Docker文件:
FROM phusion/baseimage
RUN touch /root/uid-$UID
用 docker build -t=docktest .
测试它,然后 docker run docktest ls -al /root
显示文件只是简单地命名为 uid-
.
有没有办法在来宾构建过程中与 Docker 共享主机环境变量?
这是不可能的,而且可能永远不可能,因为保持构建独立于机器的设计理念。 Issue 6822.
环境不是共享的,您可以使用-e, --env 选项在容器中设置环境变量。
当我想拥有相同的映射卷所有者时,我通常使用这种方法:我检查容器中目录的 uid 和 gid,然后创建一个相应的用户。这是我的脚本 (setuser.sh),它为目录创建一个用户:
#!/bin/bash
setuser() {
if [ -z "" ]; then
echo "Usage: [=10=] <path>"
return
fi
CURRENT_UID=`id -u`
DEST_UID=`stat -c "%u" `
if [ $CURRENT_UID = $DEST_UID ]; then
return
fi
DEST_GID=`stat -c "%g" `
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
这是以用户身份运行命令的包装脚本,其中具有权限的目录指定为 $USER_DIR 或 /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 建议采用不同的方法:将用户和组文件映射到容器中并指定 uid 和 gid。所以你的容器不依赖于内置 users/groups 你可以在没有额外脚本的情况下使用它。
我稍微修改了@ISanych 的回答:
#!/usr/bin/env bash
user_exists() {
id -u > /dev/null 2>&1
}
group_exists() {
id -g > /dev/null 2>&1
}
setuser() {
if [[ "$#" != 3 ]]; then
echo "Usage: [=10=] <path> <user> <group>"
return
fi
local dest_uid=$(stat -c "%u" )
local dest_gid=$(stat -c "%g" )
if user_exists $dest_uid; then
id -nu $dest_uid
return
fi
local dest_user=
local dest_group=
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
函数接受您要分配给所提供目录的 uid 和 gid 的用户名和组名。然后,如果具有这样的 uid 的用户存在,那么它只是 returns 对应于这个 uid 的登录,否则它创建用户和组,并且 returns 登录最初传递给函数。
所以你得到了拥有目标目录的用户的登录。
在研究此问题的解决方案时,我发现以下文章是一个很好的资源:https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf
在我的脚本中,解决方案归结为以下内容:
docker run --user $(id -u):$(id -g) -v /hostdirectory:/containerdirectory -v /etc/passwd:/etc/passwd myimage
当然,id -u
可以换成其他获取用户gid的方式,比如stat -c "%u" /somepath
我正在尝试使用卷共享在 Docker 来宾中共享文件。为了获得相同的 UID,并因此与这些文件进行互操作,我想在 Docker guest 中创建一个与我自己的用户具有相同 UID 的用户。
为了验证这个想法,我写了以下简单的Docker文件:
FROM phusion/baseimage
RUN touch /root/uid-$UID
用 docker build -t=docktest .
测试它,然后 docker run docktest ls -al /root
显示文件只是简单地命名为 uid-
.
有没有办法在来宾构建过程中与 Docker 共享主机环境变量?
这是不可能的,而且可能永远不可能,因为保持构建独立于机器的设计理念。 Issue 6822.
环境不是共享的,您可以使用-e, --env 选项在容器中设置环境变量。
当我想拥有相同的映射卷所有者时,我通常使用这种方法:我检查容器中目录的 uid 和 gid,然后创建一个相应的用户。这是我的脚本 (setuser.sh),它为目录创建一个用户:
#!/bin/bash
setuser() {
if [ -z "" ]; then
echo "Usage: [=10=] <path>"
return
fi
CURRENT_UID=`id -u`
DEST_UID=`stat -c "%u" `
if [ $CURRENT_UID = $DEST_UID ]; then
return
fi
DEST_GID=`stat -c "%g" `
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
这是以用户身份运行命令的包装脚本,其中具有权限的目录指定为 $USER_DIR 或 /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 建议采用不同的方法:将用户和组文件映射到容器中并指定 uid 和 gid。所以你的容器不依赖于内置 users/groups 你可以在没有额外脚本的情况下使用它。
我稍微修改了@ISanych 的回答:
#!/usr/bin/env bash
user_exists() {
id -u > /dev/null 2>&1
}
group_exists() {
id -g > /dev/null 2>&1
}
setuser() {
if [[ "$#" != 3 ]]; then
echo "Usage: [=10=] <path> <user> <group>"
return
fi
local dest_uid=$(stat -c "%u" )
local dest_gid=$(stat -c "%g" )
if user_exists $dest_uid; then
id -nu $dest_uid
return
fi
local dest_user=
local dest_group=
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
函数接受您要分配给所提供目录的 uid 和 gid 的用户名和组名。然后,如果具有这样的 uid 的用户存在,那么它只是 returns 对应于这个 uid 的登录,否则它创建用户和组,并且 returns 登录最初传递给函数。
所以你得到了拥有目标目录的用户的登录。
在研究此问题的解决方案时,我发现以下文章是一个很好的资源:https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf
在我的脚本中,解决方案归结为以下内容:
docker run --user $(id -u):$(id -g) -v /hostdirectory:/containerdirectory -v /etc/passwd:/etc/passwd myimage
当然,id -u
可以换成其他获取用户gid的方式,比如stat -c "%u" /somepath