管理Docker共享卷权限的(最佳)方式是什么?
我一直在玩docker一段时间,并在处理持久数据时继续发现同样的问题。
我创建了Dockerfile
并公开了卷,或者使用--volumes-from
在我的容器中安装主机文件夹
我的问题是,我应该对主机上的共享卷应用什么权限? 我可以想到2个选项:
到目前为止,我一直在做的是,给每个人读/写权限,以便我可以从码头容器中写入文件夹
将主机中的用户映射到容器中,以便我可以分配更细化的权限。 不知道这是可能的,但没有发现太多。 到目前为止,我所能做的就是以某个用户的身份运行容器: docker run -i -t -user="myuser" postgres
,但该用户与我的主机myuser
具有不同的UID,因此权限不起作用。 另外,我不确定映射用户是否会带来一些安全风险。
任何其他的选择?
你们怎么处理这个问题?
更新2016-03-02 :从Docker 1.9.0开始,Docker已经命名了可替换纯数据容器的卷。 下面的答案以及我的链接的博客帖子,仍然具有如何考虑Docker中的数据的意义,但考虑使用命名卷来实现下面描述的模式,而不是数据容器。
我相信解决这个问题的标准方法是使用纯数据容器。 采用这种方法,所有对卷数据的访问都是通过使用-volumes-from
数据容器的-volumes-from
容器进行的,因此主机uid / gid无关紧要。
例如,文档中给出的一个用例是备份数据卷。 为此,另一个容器用于通过tar
进行备份,并且它也使用-volumes-from
来装入卷。 所以我认为grok的关键点是:不要考虑如何以适当的权限访问主机上的数据,而是考虑如何做到你需要的任何事情 - 备份,浏览等 - 通过另一个容器。 容器本身需要使用一致的uid / gid,但它们不需要映射到主机上的任何东西,从而保持便携。
这对我来说也是比较新的,但是如果你有一个特定的用例可以随意发表评论,我会试着扩展答案。
更新 :对于评论中的给定用例,您可能会有some/graphite
图像用于运行石墨,以及some/graphitedata
图像用作数据容器。 所以,忽略端口等,image some/graphitedata
的Dockerfile
就像这样:
FROM debian:jessie
# add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later
RUN groupadd -r graphite
&& useradd -r -g graphite graphite
RUN mkdir -p /data/graphite
&& chown -R graphite:graphite /data/graphite
VOLUME /data/graphite
USER graphite
CMD ["echo", "Data container for graphite"]
构建并创建数据容器:
docker build -t some/graphitedata Dockerfile
docker run --name graphitedata some/graphitedata
some/graphite
Dockerfile也应该得到相同的uid / gid,因此它可能看起来像这样:
FROM debian:jessie
# add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later
RUN groupadd -r graphite
&& useradd -r -g graphite graphite
# ... graphite installation ...
VOLUME /data/graphite
USER graphite
CMD ["/bin/graphite"]
它将运行如下:
docker run --volumes-from=graphitedata some/graphite
好的,现在,我们可以将我们的石墨容器和相关数据专用容器提供给用户/组(注意,您也可以重复使用some/graphite
容器作为数据容器,在运行时覆盖入口/ cmd,但是让他们作为独立的图像IMO更清晰)。
现在,让我们说你想编辑数据文件夹中的东西。 因此,不要将卷挂载到主机并在那里编辑,而是创建一个新的容器来完成这项工作。 让我们叫它some/graphitetools
。 让我们也创建适当的用户/组,就像some/graphite
图像一样。
FROM debian:jessie
# add our user and group first to make sure their IDs get assigned consistently, regardless of other deps added later
RUN groupadd -r graphite
&& useradd -r -g graphite graphite
VOLUME /data/graphite
USER graphite
CMD ["/bin/bash"]
你可以通过在Dockerfile中继承some/graphite
或者some/graphitedata
来做到这一点,或者不用创建一个新的镜像,而是重新使用现有的镜像(根据需要重写入口点/ cmd)。
现在,你只需运行:
docker run -ti --rm --volumes-from=graphitedata some/graphitetools
然后vi /data/graphite/whatever.txt
。 这完美地工作,因为所有的容器都有相同的石墨用户与uid / gid匹配。
由于您从不从主机安装/data/graphite
,因此您不必关心主机uid / gid如何映射到graphite
和graphitetools
容器中定义的uid / gid。 这些容器现在可以部署到任何主机,并且它们将继续完美工作。
关于这一点很简单,就是graphitetools
可以有各种有用的实用程序和脚本,现在您也可以以便携的方式进行部署。
更新2 :在写这个答案之后,我决定写一篇关于这种方法的更完整的博客文章。 我希望它有帮助。
更新3 :我更正了这个答案并添加了更多细节。 它之前包含了关于所有权和权限的一些不正确的假设 - 所有权通常是在创建卷时(即在数据容器中)分配的,因为这是创建卷时的情况。 看到这个博客。 但这不是必需的 - 您可以将数据容器用作“引用/句柄”,并通过chown在入口点中将另一个容器中的所有权/权限设置为gosu,以便以正确的用户身份运行该命令。 如果有人对此方法感兴趣,请发表评论,我可以提供使用此方法的示例链接。
官方redis映像和所有官方映像中都可以看到非常优雅的解决方案。
逐步描述过程描述:
正如在Dockerfile中所看到的那样:
首先添加我们的用户和组,以确保其ID一致地分配,而不管添加的任何依赖关系如何
gosu是su
/ sudo
的另一种选择,可以轻松从root用户降级。 (Redis总是使用redis
用户运行)
/data
卷并将其设置为workdir 通过使用VOLUME /data
命令配置/ data卷,我们现在有一个单独的卷,可以是docker卷或绑定安装到主机目录。
将其配置为workdir( WORKDIR /data
)使其成为执行命令的默认目录。
这意味着所有容器执行都将通过docker-entrypoint脚本运行,默认情况下要运行的命令是redis-server。
docker-entrypoint
是一个执行简单功能的脚本:更改当前目录(/ data)的所有权,并从root
用户redis-server
更改为redis
用户,以运行redis-server
。 (如果执行的命令不是redis-server,它将直接运行该命令。)
这具有以下效果
如果将/ data目录绑定到主机上,docker-entrypoint将在redis
用户下运行redis-server之前准备好用户权限。
这使您可以轻松地进行零设置,以便在任何卷配置下运行容器。
当然,如果你需要在不同的图像之间共享卷,你需要确保它们使用相同的userid / groupid,否则最新的容器会劫持前一个用户的权限。
这可能不是大多数情况下最好的方式,但它尚未提及,所以它可能会帮助某人。
绑定安装主机卷
Host folder FOOBAR is mounted in container /volume/FOOBAR
修改您的容器的启动脚本以查找您感兴趣的卷的GID
$ TARGET_GID=$(stat -c "%g" /volume/FOOBAR)
确保您的用户属于使用此GID的组(您可能必须创建一个新组)。 在这个例子中,我假装我的软件在容器内部作为nobody
用户运行,所以我想确保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
子句一起使用(除非该用户具有我认为的root权限)。 另外,它尖叫黑客的工作;-)
如果你想硬核,你可以用很多方式来扩展它 - 例如搜索任何子文件,多卷等的所有组。
链接地址: http://www.djcxy.com/p/18243.html上一篇: What is the (best) way to manage permissions for docker shared volumes