运行 特定用户命名空间配置中的每个 Docker 容器
Run each Docker container in a specific user namespace configuration
问题:
我正在尝试以这种方式将目录挂载为 Docker 卷,
在容器内创建的用户可以写
到该卷中的文件中。同时,该文件应
至少在容器外对我的用户 lape
是可读的。
基本上,我需要将用户 UID 从容器用户命名空间重新映射到主机用户命名空间上的特定 UID。
我该怎么做?
我更喜欢这样的答案:
- 不涉及更改 Docker 守护进程的方式 运行;
- 并允许为每个容器单独配置容器用户命名空间;
- 不需要重建映像;
- 我会接受显示使用 Access Control Lists 的不错解决方案的答案;
设置:
这是可以复制的情况。
我有我的 Linux 用户 lape
,分配给 docker
组,所以我
可以 运行 Docker 容器而不是 root。
lape@localhost ~ $ id
uid=1000(lape) gid=1000(lape) groups=1000(lape),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),121(lpadmin),131(sambashare),999(docker)
Docker文件:
FROM alpine
RUN apk add --update su-exec && rm -rf /var/cache/apk/*
# I create a user inside the image which i want to be mapped to my `lape`
RUN adduser -D -u 800 -g 801 insider
VOLUME /data
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["sh", "/entrypoint.sh"]
entrypoint.sh:
#!/bin/sh
chmod 755 /data
chown insider:insider /data
# This will run as `insider`, and will touch a file to the shared volume
# (the name of the file will be current timestamp)
su-exec insider:insider sh -c 'touch /data/$(date +%s)'
# Show permissions of created files
ls -las /data
构建后:
docker build -t nstest
我运行容器:
docker run --rm -v $(pwd)/data:/data nstest
输出如下:
total 8
4 drwxr-xr-x 2 insider insider 4096 Aug 26 08:44 .
4 drwxr-xr-x 31 root root 4096 Aug 26 08:44 ..
0 -rw-r--r-- 1 insider insider 0 Aug 26 08:44 1503737079
所以文件似乎是作为用户 insider
.
创建的
在我的主机上,权限如下所示:
lape@localhost ~ $ ls -las ./data
total 8
4 drwxr-xr-x 2 800 800 4096 Aug 26 09:44 .
4 drwxrwxr-x 3 lape lape 4096 Aug 26 09:43 ..
0 -rw-r--r-- 1 800 800 0 Aug 26 09:44 1503737079
这表明该文件属于 uid=800(即 insider
用户甚至不存在于 Docker 命名空间之外)。
我已经尝试过的事情:
我尝试将 --user
参数指定为 docker run
,但它似乎只能映射主机上的哪个用户被映射到 docker 命名空间,在我的例子中 insider
不是 root。所以在这种情况下它并没有真正起作用。
我从容器中实现 insider
(uid=800) 的唯一方法是添加 --userns-remap="default"
到 dockerd
启动脚本,并按照 documentation for --userns-remap 中的建议将 dockremap:200:100000
添加到文件 /etc/subuid
和 /etc/subgid
。巧合的是这对我有用,但它不是充分的解决方案,因为:
- 它需要重新配置 Docker 守护进程 运行s;
的方式
- 需要对用户 ID 进行一些运算:'200 = 1000 - 800',其中 1000 是主机上我的用户的 UID,800 是
insider
用户的 UID;
- 如果内部用户需要比我的主机用户更高的 UID,那甚至都行不通;
- 它只能配置用户命名空间如何全局映射,无法对每个容器进行唯一配置;
- 这种解决方案可行,但对于实际使用来说有点太难看了。
如果您只需要您的用户的读取权限,最简单的方法是使用 docker.[=13= 之外的 acls 添加 /data
中所有文件和子目录的读取权限]
添加默认 acl:setfacl -d -m u:lape:-rx /data
.
您还需要授予对目录本身的访问权限:setfacl -m u:lape:-rx /data
.
这样的解决方案有什么障碍吗?
问题:
我正在尝试以这种方式将目录挂载为 Docker 卷,
在容器内创建的用户可以写
到该卷中的文件中。同时,该文件应
至少在容器外对我的用户 lape
是可读的。
基本上,我需要将用户 UID 从容器用户命名空间重新映射到主机用户命名空间上的特定 UID。
我该怎么做?
我更喜欢这样的答案:
- 不涉及更改 Docker 守护进程的方式 运行;
- 并允许为每个容器单独配置容器用户命名空间;
- 不需要重建映像;
- 我会接受显示使用 Access Control Lists 的不错解决方案的答案;
设置:
这是可以复制的情况。
我有我的 Linux 用户 lape
,分配给 docker
组,所以我
可以 运行 Docker 容器而不是 root。
lape@localhost ~ $ id
uid=1000(lape) gid=1000(lape) groups=1000(lape),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),121(lpadmin),131(sambashare),999(docker)
Docker文件:
FROM alpine
RUN apk add --update su-exec && rm -rf /var/cache/apk/*
# I create a user inside the image which i want to be mapped to my `lape`
RUN adduser -D -u 800 -g 801 insider
VOLUME /data
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["sh", "/entrypoint.sh"]
entrypoint.sh:
#!/bin/sh
chmod 755 /data
chown insider:insider /data
# This will run as `insider`, and will touch a file to the shared volume
# (the name of the file will be current timestamp)
su-exec insider:insider sh -c 'touch /data/$(date +%s)'
# Show permissions of created files
ls -las /data
构建后:
docker build -t nstest
我运行容器:
docker run --rm -v $(pwd)/data:/data nstest
输出如下:
total 8
4 drwxr-xr-x 2 insider insider 4096 Aug 26 08:44 .
4 drwxr-xr-x 31 root root 4096 Aug 26 08:44 ..
0 -rw-r--r-- 1 insider insider 0 Aug 26 08:44 1503737079
所以文件似乎是作为用户 insider
.
在我的主机上,权限如下所示:
lape@localhost ~ $ ls -las ./data
total 8
4 drwxr-xr-x 2 800 800 4096 Aug 26 09:44 .
4 drwxrwxr-x 3 lape lape 4096 Aug 26 09:43 ..
0 -rw-r--r-- 1 800 800 0 Aug 26 09:44 1503737079
这表明该文件属于 uid=800(即 insider
用户甚至不存在于 Docker 命名空间之外)。
我已经尝试过的事情:
我尝试将
--user
参数指定为docker run
,但它似乎只能映射主机上的哪个用户被映射到 docker 命名空间,在我的例子中insider
不是 root。所以在这种情况下它并没有真正起作用。我从容器中实现
insider
(uid=800) 的唯一方法是添加--userns-remap="default"
到dockerd
启动脚本,并按照 documentation for --userns-remap 中的建议将dockremap:200:100000
添加到文件/etc/subuid
和/etc/subgid
。巧合的是这对我有用,但它不是充分的解决方案,因为:- 它需要重新配置 Docker 守护进程 运行s; 的方式
- 需要对用户 ID 进行一些运算:'200 = 1000 - 800',其中 1000 是主机上我的用户的 UID,800 是
insider
用户的 UID; - 如果内部用户需要比我的主机用户更高的 UID,那甚至都行不通;
- 它只能配置用户命名空间如何全局映射,无法对每个容器进行唯一配置;
- 这种解决方案可行,但对于实际使用来说有点太难看了。
如果您只需要您的用户的读取权限,最简单的方法是使用 docker.[=13= 之外的 acls 添加 /data
中所有文件和子目录的读取权限]
添加默认 acl:setfacl -d -m u:lape:-rx /data
.
您还需要授予对目录本身的访问权限:setfacl -m u:lape:-rx /data
.
这样的解决方案有什么障碍吗?