我使用Docker已经有一段时间了,在处理持久数据时不断发现同样的问题。

我创建Dockerfile并公开一个卷或使用——volumes-from在容器中挂载一个主机文件夹。

主机上的共享卷需要申请哪些权限?

我可以想到两个选择:

So far I've given everyone read/write access, so I can write to the folder from the Docker container. Map the users from host into the container, so I can assign more granular permissions. Not sure this is possible though and haven't found much about it. So far, all I can do is run the container as some user: docker run -i -t -user="myuser" postgres, but this user has a different UID than my host myuser, so permissions do not work. Also, I'm unsure if mapping the users will pose some security risks.

还有其他选择吗?

你们是如何处理这个问题的?


当前回答

在大多数情况下,这可能不是最好的方法,但它还没有被提及,所以也许它会帮助到某些人。

绑定挂载主机卷 主机文件夹FOOBAR挂载在容器/卷/FOOBAR中 修改容器的启动脚本,以找到感兴趣的卷的GID $ TARGET_GID=$(stat -c "%g" /volume/FOOBAR) 确保您的用户属于一个具有此GID的组(您可能必须创建一个新组)。对于本例,我将假装我的软件在容器内以nobody用户运行,因此我希望确保没有人属于组id等于TARGET_GID的组

  EXISTS=$(cat /etc/group | grep $TARGET_GID | wc -l)

  # Create new group using target GID and add nobody user
  if [ $EXISTS == "0" ]; then
    groupadd -g $TARGET_GID tempgroup
    usermod -a -G tempgroup nobody
  else
    # GID exists, find group name and add
    GROUP=$(getent group $TARGET_GID | cut -d: -f1)
    usermod -a -G $GROUP nobody
  fi

我喜欢这样做是因为我可以轻松地修改主机卷上的组权限,并且知道这些更新的权限适用于docker容器内部。这种情况无需对我的主机文件夹/文件进行任何权限或所有权修改,这让我很高兴。

我不喜欢这种方法,因为它假定将自己添加到容器内的任意组(碰巧使用您想要的GID)中没有危险。它不能与Dockerfile中的USER子句一起使用(除非该用户具有根权限)。此外,它是一种黑客工作;-)

如果你想要硬核,你显然可以在许多方面扩展它——例如,搜索任何子文件上的所有组,多个卷,等等。

其他回答

这里有一种方法,它仍然使用纯数据容器,但不要求它与应用程序容器同步(就具有相同的uid/gid而言)。

假设,你想在容器中运行一些应用程序作为非根$USER没有登录shell。

在Dockerfile中:

RUN useradd -s /bin/false myuser

# Set environment variables
ENV VOLUME_ROOT /data
ENV USER myuser

...

ENTRYPOINT ["./entrypoint.sh"]

然后,在entrypoint.sh中:

chown -R $USER:$USER $VOLUME_ROOT
su -s /bin/bash - $USER -c "cd $repo/build; $@"

和你一样,我正在寻找一种将用户/组从主机映射到docker容器的方法,这是迄今为止我发现的最短的方法:

  version: "3"
  services:
    my-service:
      .....
      volumes:
        # take uid/gid lists from host
        - /etc/passwd:/etc/passwd:ro
        - /etc/group:/etc/group:ro
        # mount config folder
        - path-to-my-configs/my-service:/etc/my-service:ro
        .....

这是从docker-compose.yml中提取的。

其思想是(以只读模式)将用户/组列表从主机挂载到容器,这样容器启动后,它将具有与主机相同的uid->用户名(以及组)匹配。现在,您可以在容器中为服务配置用户/组设置,就像它在您的主机系统上工作一样。

当您决定将容器移动到另一个主机时,您只需要将服务配置文件中的用户名更改为该主机上的用户名。

在大多数情况下,这可能不是最好的方法,但它还没有被提及,所以也许它会帮助到某些人。

绑定挂载主机卷 主机文件夹FOOBAR挂载在容器/卷/FOOBAR中 修改容器的启动脚本,以找到感兴趣的卷的GID $ TARGET_GID=$(stat -c "%g" /volume/FOOBAR) 确保您的用户属于一个具有此GID的组(您可能必须创建一个新组)。对于本例,我将假装我的软件在容器内以nobody用户运行,因此我希望确保没有人属于组id等于TARGET_GID的组

  EXISTS=$(cat /etc/group | grep $TARGET_GID | wc -l)

  # Create new group using target GID and add nobody user
  if [ $EXISTS == "0" ]; then
    groupadd -g $TARGET_GID tempgroup
    usermod -a -G tempgroup nobody
  else
    # GID exists, find group name and add
    GROUP=$(getent group $TARGET_GID | cut -d: -f1)
    usermod -a -G $GROUP nobody
  fi

我喜欢这样做是因为我可以轻松地修改主机卷上的组权限,并且知道这些更新的权限适用于docker容器内部。这种情况无需对我的主机文件夹/文件进行任何权限或所有权修改,这让我很高兴。

我不喜欢这种方法,因为它假定将自己添加到容器内的任意组(碰巧使用您想要的GID)中没有危险。它不能与Dockerfile中的USER子句一起使用(除非该用户具有根权限)。此外,它是一种黑客工作;-)

如果你想要硬核,你显然可以在许多方面扩展它——例如,搜索任何子文件上的所有组,多个卷,等等。

要在docker主机和docker容器之间共享文件夹,请尝试以下命令

$(pwd):$(pwd)-i -t ubuntu

-v标志将当前工作目录挂载到容器中。当绑定挂载卷的主机目录不存在时,Docker会自动在主机上为你创建这个目录,

然而,这里有两个问题:

如果您不是root用户,则无法对挂载的卷进行写操作,因为共享文件将由主机中的其他用户拥有。 你不应该以root用户在容器中运行进程,但即使你以硬编码用户运行,它仍然不会与你笔记本电脑上的用户匹配。

解决方案:

容器: 创建一个用户testuser,默认用户id从1000开始,

主持人: 创建一个名为“testgroup”的组,组id为1000,并将目录更改为新组(testgroup . testgroup . testgroup)

为了保护和更改docker容器和docker主机的根,请尝试使用——uidmap和——private-uids选项

https://github.com/docker/docker/pull/4572#issuecomment-38400893

此外,您还可以删除docker容器中的几个功能(——cap-drop)以确保安全性

http://opensource.com/business/14/9/security-for-docker

更新支持应该出现在docker > 1.7.0中

更新版本1.10.0 (2016-02-04)add——users -remap标志 https://github.com/docker/docker/blob/master/CHANGELOG.md#security-2