2016-03-02 更新:从 Docker 1.9.0 开始,Docker 有 named volumes 和 replace data-only containers。下面的答案以及我链接的博客文章在如何考虑 docker 中的数据方面仍然具有价值,但请考虑使用命名卷来实现下面描述的模式,而不是数据容器。
我相信解决这个问题的规范方法是使用data-only containers。使用这种方法,对卷数据的所有访问都是通过使用 -volumes-from 数据容器的容器进行的,因此主机 uid/gid 无关紧要。
例如,文档中给出的一个用例是备份数据卷。为此,另一个容器用于通过tar 进行备份,它也使用-volumes-from 来挂载卷。所以我认为 grok 的关键点是:与其考虑如何以适当的权限访问主机上的数据,不如考虑如何通过另一个容器做任何你需要的事情——备份、浏览等。 .容器本身需要使用一致的 uid/gids,但它们不需要映射到主机上的任何东西,从而保持可移植性。
这对我来说也相对较新,但如果您有特定的用例,请随时发表评论,我会尝试扩展答案。
更新:对于 cmets 中的给定用例,您可能有一个映像 some/graphite 来运行石墨,以及一个映像 some/graphitedata 作为数据容器。因此,忽略端口等,图像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/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 图像一样。
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 继承来使这个 DRY,或者不创建新映像,只需重新使用现有映像之一(根据需要覆盖入口点/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:写完这个答案后,我决定写一个more complete blog post 来介绍这种方法。希望对你有帮助。
更新 3:我更正了这个答案并添加了更多细节。它以前包含一些关于所有权和权限的错误假设——所有权通常是在创建卷时分配的,即在数据容器中,因为那是创建卷的时候。见this blog。但这不是必需的——您可以将数据容器用作“参考/句柄”,并通过入口点中的 chown 在另一个容器中设置所有权/权限,最后以 gosu 结尾,以正确用户身份运行命令。如果有人对此方法感兴趣,请发表评论,我可以提供指向使用此方法的示例的链接。