我一直在使用 Docker,并且在处理持久数据时不断发现同样的问题。
我创建Dockerfile并公开一个卷或用于在我的容器--volumes- from中安装一个主机文件夹。 我应该对主机上的共享卷应用什么权限?
Dockerfile
--volumes- from
我可以想到两个选择:
到目前为止,我已经为每个人提供了读/写访问权限,因此我可以从 Docker 容器写入文件夹。
将主机中的用户映射到容器中,这样我就可以分配更精细的权限。虽然不确定这是可能的,但还没有找到太多关于它的信息。到目前为止,我所能做的就是以某个用户身份运行容器:docker run -i -t -user="myuser" postgres,但是这个用户的 UID 与我的主机不同myuser,所以权限不起作用。另外,我不确定映射用户是否会带来一些安全风险。
docker run -i -t -user="myuser" postgres
myuser
还有其他选择吗?
你们是如何处理这个问题的?
更新 2016-03-02 :从 Docker 1.9.0 开始,Docker 已命名卷来替换纯数据容器。下面的答案以及我链接的博客文章在 如何考虑 docker 内部的数据 方面仍然具有价值,但考虑使用命名卷来实现下面描述的模式而不是数据容器。
我相信解决这个问题的规范方法是使用data-only containers。使用这种方法,对卷数据的所有访问都是通过使用-volumes- from数据容器的容器进行的,因此主机 uid/gid 无关紧要。
-volumes- from
例如,文档中给出的一个用例是备份数据卷。为此,另一个容器用于通过 进行备份tar,它也用于-volumes-from挂载卷。所以我认为 grok 的关键点是:与其考虑如何以适当的权限访问主机上的数据,不如考虑如何通过另一个容器做任何你需要的事情——备份、浏览等。 . 容器本身需要使用一致的 uid/gids,但它们不需要映射到主机上的任何东西,从而保持可移植性。
tar
-volumes-from
这对我来说也相对较新,但是如果您有特定的用例,请随时发表评论,我会尝试扩展答案。
更新 :对于评论中的给定用例,您可能有一个some/graphite运行石墨的图像,以及一个some/graphitedata作为数据容器的图像。因此,忽略端口等,Dockerfile图像some/graphitedata类似于:
some/graphite
some/graphitedata
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
Dockerfilesome/graphite也应该获得相同的 uid/gids,因此它可能看起来像这样:
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容器重新用于数据容器,在运行它时覆盖 entrypoing/cmd,但将它们作为单独的图像 IMO 更清晰)。
现在,假设您要编辑数据文件夹中的某些内容。因此,与其将卷绑定到主机并在那里进行编辑,不如创建一个新容器来完成这项工作。让我们称之为some/graphitetools。让我们也创建适当的用户/组,就像some/graphite图像一样。
some/graphitetools
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"]
some/graphite您可以通过从 Dockerfile 继承或在 Dockerfile 中继承来使此 DRY some/graphitedata,或者不创建新映像,只需重新使用现有映像之一(根据需要覆盖 entrypoint/cmd)。
现在,您只需运行:
docker run -ti --rm --volumes-from=graphitedata some/graphitetools
然后vi /data/graphite/whatever.txt。这非常有效,因为所有容器都有相同的石墨用户和匹配的 uid/gid。
vi /data/graphite/whatever.txt
由于您从不从主机挂载/data/graphite,因此您不关心主机 uid/gid 如何映射到graphite和graphitetools容器内定义的 uid/gid。这些容器现在可以部署到任何主机上,并且它们将继续完美运行。
/data/graphite
graphite
graphitetools
这样做的好处是它graphitetools可以拥有各种有用的实用程序和脚本,您现在还可以以可移植的方式部署它们。
更新2 :写完这个答案后,我决定写一篇关于这种方法的更完整的博客文章。我希望它有所帮助。
更新 3 :我更正了这个答案并添加了更多细节。它以前包含一些关于所有权和权限的错误假设——所有权通常是在创建卷时分配的,即在数据容器中,因为那是创建卷的时候。看到这个博客。但这不是必需的——您可以将数据容器用作“引用/句柄”,并通过入口点中的 chown 在另一个容器中设置所有权/权限,最后以 gosu 结尾,以正确用户身份运行命令。如果有人对这种方法感兴趣,请发表评论,我可以提供使用这种方法的示例链接。