有没有办法在运行时重新映射用户ID?

时间:2018-03-21 22:34:06

标签: docker

我有一个容器,它创建了一个默认用户,其UID为1000。

在我的Dockerfile中,我正在创建用户:

RUN groupadd sudo && useradd -G sudo -u 1000 -U ${RUST_USER}

现在,当我运行容器时,除非我的当前用户具有完全UID 1000,否则批量权限将被搞砸:

docker run -it --rm naftulikay/circleci-lambda-rust:latest \
    -v $PWD:/home/circleci/project \
    .local/bin/build

在运行时:

error: failed to write /home/circleci/project/Cargo.lock

Caused by:
  failed to open: /home/circleci/project/Cargo.lock

Caused by:
  Permission denied (os error 13)
Exited with code 101

这是因为容器中的用户具有UID 1000,容器外的用户具有UID 1001.

我想,由于这已经是内核命名空间的所有虚拟映射,因此可以将内部UID映射到容器中的外部UID。

是否有命令行选项允许我根据需要动态重新映射UID?

2 个答案:

答案 0 :(得分:1)

已请求在容器和主机之间动态映射UID,但我认为它需要实现内核和文件系统更改。在那之前,您有几个选择:

  1. 使主机与容器匹配。使用主机卷,这并不容易。但是对于命名卷,docker会将卷初始化为映像的内容,包括目录和文件权限,使其相当无缝。您需要调整工作流程,以便不再直接访问卷中的数据,而是使用容器来访问数据。

  2. 将容器作为主机uid运行。您可以将/ etc / passwd作为主机卷挂载到容器中,并且可以像任何uid一样启动容器(在撰写文件中使用docker run -uuser条目)。唯一的缺点是图像中的文件可能已经由用于构建图像的uid拥有,因此它们需要是世界可读的(可能是可写的)或移动到卷。

  3. 我已经知道以root身份启动我的容器,其入口点可根据卷装入的文件权限更正uid / gid不匹配。然后,我的入口点的最后一步是删除新uid的权限并执行容器应用程序。有关执行此操作的入口点的示例,请参阅我的jenkins in docker示例,其中jenkins gid与从主机挂载的docker套接字匹配。

答案 1 :(得分:0)

BMitch所说,根据系统的不同,您有很多选择,但是请记住,您可能必须重新启动运行的进程(例如php-fpm)

一些有关如何实现此目的的示例:(您可以使用docker container exec ...在容器外部运行命令)

  • 示例1:

usermod -g 1007 www-data

它将用户www-data的uid更新为1007

  • 示例2:

deluser www-data

adduser -u 1007 -D -S -G www-data www-data

它将删除用户www-data并使用uid 1007重新创建

  • 获取pid并重新启动过程

要重新启动正在运行的进程,例如php-fpm,您可以这样做:

首先使用以下命令之一获取pid:

pidof php-fpm

ps -ef | grep -v grep | grep php-fpm | awk '{print $2}'

find /proc -mindepth 2 -maxdepth 2 -name exe -lname '*/php-fpm' -printf %h\\n 2>/dev/null | sed s+^/proc/++

然后使用之前获得的pid重新启动进程(如果进程支持USR2信号):

kill -USR2 pid <-用之前的数字替换pid

我发现最简单的方法是在知道正确的pid的情况下更新主机或构建容器(如果您在不同的环境中工作,则并非总是可行的)