具有卷装载的docker容器中的文件权限

具有卷装载的docker容器中的文件权限,docker,permissions,docker-compose,Docker,Permissions,Docker Compose,我试图让docker容器从主机文件系统访问letsencrypt证书 我不希望以root用户身份运行docker容器,而是希望以具有非常特定访问权限的用户身份运行docker容器。 我也不想更改证书的权限。 我只希望给定的用户能够读取docker容器中的证书 证书具有以下设置: -rw-r----- 1 root cert-group 要运行docker容器的用户位于证书组中: uid=113(myuser) gid=117(myuser) groups=117(myuser),999(cer

我试图让docker容器从主机文件系统访问letsencrypt证书

我不希望以root用户身份运行docker容器,而是希望以具有非常特定访问权限的用户身份运行docker容器。 我也不想更改证书的权限。 我只希望给定的用户能够读取docker容器中的证书

证书具有以下设置:

-rw-r----- 1 root cert-group
要运行docker容器的用户位于证书组中:

uid=113(myuser) gid=117(myuser) groups=117(myuser),999(cert-group),998(docker)
只要我们在主机上,它就可以工作——我可以使用用户“myuser”按预期读取文件

现在,我想在docker容器中执行此操作,证书作为卷装入。 我已经做了多个测试用例,但都没有成功

用于测试的简单docker compose文件:

version: '3.7'

services:

  test:
    image: alpine:latest
    volumes:
      - /etc/ssl/letsencrypt/cert.pem:/cert.pem:ro
    command: > 
      sh -c 'ls -l / && cat /etc/passwd && cat /etc/group && cat /cert.pem'
    user: "113:117"
    restart: "no"
这会产生很多影响,但最重要的是:

test_1  | -rw-r-----    1 root     ping          3998 Jul 15 09:51 cert.pem
test_1  | cat: can't open '/cert.pem': Permission denied
test_1  | ping:x:999:
在这里,我假设“ping”是docker alpine的一个内部组,但是,我得到了一些关于它如何与主机协作的混合信息

从本文中,我的收获是,只有一个内核处理所有权限(主机),因此如果使用相同的uid和gid,权限将从主机继承。然而,即使运行的用户是113:117,主机上的用户是999组的一部分,它仍然不允许我读取文件

接下来我发现了这篇文章,特别是这一要点引起了我的注意:

容器操作系统对在中执行的所有操作强制文件权限 容器运行时根据其自身的配置。例如 如果主机和容器中都存在用户a,则将用户a添加到组中 主机上的B将不允许用户A写入其拥有的目录 容器内的组B,除非在容器内创建了组B 容器,并将用户A添加到其中

这让我想到,可能需要一个自定义Dockerfile,以便在docker中添加用户,并使用户成为999的一部分(如前所述,称为ping):

运行此命令会得到完全相同的结果,现在将myuser附加到passwd中:

test_1  | myuser:x:113:999:Linux User,,,:/home/myuser:/sbin/nologin
这只是我尝试过的几件事

另一个是将/etc/passwd和/etc/group与其他博客中的卷同步

volumes:
  - /etc/passwd:/etc/passwd
  - /etc/group:/etc/group
这使得它在容器内部看起来是正确的,但它不会改变最终结果-仍然拒绝许可


我已经没有什么想法了,如果您能给我提供任何帮助或指点,我将不胜感激。

事实上,您的解决方案并没有错。我也这么做了,但没有什么不同

这是我的Dockerfile:

FROM alpine:latest
RUN addgroup -S cert-group -g 117 \
    && adduser -S --uid 113 -G cert-group myuser
USER myuser
还有我的docker-compose.yml:

version: '3.7'

services:

  test:
    build: 
      dockerfile: ./Dockerfile
      context: .
    command: >
      sh -c 'ls -l / && cat /etc/passwd && cat /etc/group && cat /cert.pem'
    volumes:
      - "/tmp/test.txt:/cert.pem:ro"
    restart: "no"
我的“/tmp/test.txt”被分配到113:117


IMHO,我认为docker-compose.yml中的问题在于它没有使用您的图像。您应该删除
图像:
并添加
构建:

我今天也遇到了同样的问题,幸运的是,下面的解决方案帮助了我

“将:Z添加到卷装载” 参考:


注意:不幸的是,这只是Centos的问题,我在Ubuntu上没有遇到任何问题。

Docker容器不知道主机上运行容器的用户的uid/gid。所有运行容器的请求都经过docker套接字,然后到达docker引擎,该引擎通常以root用户身份运行,在这些API调用中不传递uid/gid。docker引擎只是以docker文件中指定的用户身份或容器创建命令的一部分(在本例中,来自docker compose.yml)运行容器

进入容器后,使用容器内的/etc/passwd和/etc/group文件完成从uid/gid到names的映射。重要的是,在文件系统级别,容器和主机之间没有映射uid/gid值(用户名称空间除外,但如果实现正确,这只会使问题变得更糟)。所有文件系统操作都发生在uid/gid级别,而不是基于名称。因此,在执行主机卷装载时,uid/gid直接通过

这里遇到的问题是如何告诉容器选择uid/gid来运行容器进程。通过指定
user:“113:117”
您告诉容器不仅要指定进程的uid(113),还要指定进程的gid(117)。完成后,
/etc/group
中的任何辅助组都不会分配给用户。要分配这些辅助组,只需指定uid,
用户:“113”
,然后它将从容器内的
/etc/passwd
/etc/group
文件中查找组分配。例如:

user: "113"

不幸的是,在装入任何卷之前,docker都会查找组成员身份,因此出现以下情况

首先,创建一个图像,将示例用户分配到几个组:

$ cat df.users 
FROM alpine:latest

RUN addgroup -g 4242 group1 \
 && addgroup -g 8888 group2 \
 && adduser  -u 1000 -D -H test \
 && addgroup test group1 \
 && addgroup test group2

$ docker build -t test-users -f df.users .
...
接下来,运行该映像,将主机上的id与容器内的id进行比较:

$ id
uid=1000(bmitch) gid=1000(bmitch) groups=1000(bmitch),24(cdrom),25(floppy),...

$ docker run -it --rm -u bmitch -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro test-users:latest id
docker: Error response from daemon: unable to find user bmitch: no matching entries in passwd file.
Woops,docker没有看到/etc/passwd中的条目,让我们试试我们在图像中创建的
test
用户:

$ docker run -it --rm -u test -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro test-users:latest id
uid=1000(bmitch) gid=1000(bmitch) groups=4242,8888
这是可行的,并从映像中的
/etc/group
文件分配组,而不是我们装载的组。我们还可以看到uid也可以工作:

$ docker run -it --rm -u 1000 -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro test-users:latest id
uid=1000(bmitch) gid=1000(bmitch) groups=4242,8888
一旦我们指定gid,辅助组就会消失:

$ docker run -it --rm -u 1000:1000 -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro test-users:latest id
uid=1000(bmitch) gid=1000(bmitch)
如果我们运行时没有覆盖
/etc/passwd
/etc/group
文件,我们可以看到正确的权限:

$ docker run -it --rm -u test test-users:latest id
uid=1000(test) gid=1000(test) groups=4242(group1),8888(group2)

最好的选择可能是添加一个容器用户,其组成员身份与主机的uid/gid值匹配。对于主机卷,我还通过一个基本映像解决了这个问题,该映像动态调整容器中的用户或组,以匹配卷中装入的文件的uid/gid。这是以root用户身份完成的,然后使用gosu将权限放回用户。你可以在github上看到,speci
$ docker run -it --rm -u test test-users:latest id
uid=1000(test) gid=1000(test) groups=4242(group1),8888(group2)