管理Docker共享卷权限的(最佳)方法是什么? [英] What is the (best) way to manage permissions for Docker shared volumes?
问题描述
我已经和Docker玩了一段时间了,在处理持久性数据时一直寻找相同的问题。
我创建了 Dockerfile
和公开卷或使用-volumes-from
到在容器中安装主机文件夹。
我应该对主机上的共享卷应用哪些权限?
我可以想到两个选择:
-
到目前为止,我已经给大家读过/写访问权限,因此我可以从Docker容器中写入文件夹。
-
将用户从主机映射到容器中,这样我就可以分配更精细的权限。不确定是否可行,但尚未找到很多相关信息。到目前为止,我所能做的就是以某些用户身份运行容器:
docker run -i -t -user = myuser postgres
,但是该用户的UID与我的主机myuser
,因此权限不起作用。另外,我不确定映射用户是否会带来一些安全风险。
还有其他选择吗?
你们如何处理这个问题?
UPDATE 2016-03-02 :自Docker 1.9.0起,Docker具有命名卷 替换仅数据容器。下面的答案以及我链接的博客文章,在如何考虑docker内部的数据的意义上仍然有价值,但请考虑使用命名卷而不是数据容器来实现以下所述的模式。 / p>
我相信解决此问题的规范方法是使用仅数据容器。通过这种方法,所有对卷数据的访问都是通过使用 -volumes-from
数据容器的容器进行的,因此主机uid / gid无关紧要。
例如,文档中给出的一个用例正在备份数据量。为此,使用另一个容器通过 tar
进行备份,并且它也按顺序使用 -volumes-from
安装卷。因此,我认为grok的关键点是:与其考虑如何通过适当的权限访问主机上的数据,不如考虑如何通过另一个容器来执行所需的任何操作(备份,浏览等)。 。容器本身需要使用一致的uid / gids,但是它们不需要映射到主机上的任何内容,从而保持可移植性。
对我来说这是相对较新的同样,但是如果您有特定的用例,请随时发表评论,我将尝试扩展答案。
更新:对于在注释中给定的用例中,您可能有一个图像 some / graphite
来运行石墨,以及一个图像 some / graphitedata
作为数据容器。因此,忽略端口等,图像 some / graphitedata
的 Dockerfile
类似于:
FROM debian:jessie
#首先添加我们的用户和组,以确保其ID得到一致分配,而不管后来添加的其他dep为何$ b RUN groupadd -r石墨\
&& useradd -r -g石墨石墨
RUN mkdir -p / data / graphite \
&& chown -R石墨:石墨/数据/石墨
体积/数据/石墨
用户石墨
CMD [ echo,石墨的数据容器]
构建并创建数据容器:
docker build -t some / graphitedata Dockerfile
docker run --name石墨数据some / graphitedata
some / graphite
Dockerfile也应该获得相同的uid / gids,因此可能看起来像这样:
FROM debian:jessie
#首先添加我们的用户和组,以确保其ID得到一致分配,而不管后来添加的其他deps是什么。
RUN groupadd -r石墨b
&& useradd -r -g石墨石墨
#...石墨安装...
体积/ data / graphite
用户石墨
CMD [ / bin / graphite]
运行如下:
docker run --volumes-from = graphitedata一些/石墨
好的,现在,我们为石墨容器和关联的仅数据容器提供了正确的用户/组(请注意,您可以将 some / graphite
容器重新用于数据容器同样,在运行时覆盖entrypoing / cmd,但将它们作为单独的图像IMO会更清晰。)
现在,假设您要编辑数据中的内容夹。因此,与其将卷绑定到主机上并在其上进行编辑,不如创建一个新容器来完成该工作。我们称之为 some / graphitetools
。让我们还创建适当的用户/组,就像 some / graphite
图片一样。
FROM debian:jessie
#首先添加我们的用户和组,以确保其ID得到一致分配,而不管以后是否添加了其他部门
RUN groupadd -r石墨\
& ;& useradd -r -g石墨石墨
VOLUME / data / graphite
用户石墨
CMD [ / bin / bash]
您可以通过从 some / graphite
或 some / graphitedata继承来进行此DRY code>而不是创建新映像,而只是重用现有映像之一(必要时覆盖入口点/ 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
可能具有各种有用的实用程序和脚本,您现在也可以以可移植的方式进行部署。
UPDATE 2 :写下此答案后,我决定撰写有关以下内容的更完整的博客文章这种方法。希望对您有所帮助。
更新3 :我更正了这个答案,并添加了更多细节。它先前包含有关所有权和权限的一些错误假设-所有权通常是在卷创建时即在数据容器中分配的,因为那是在创建卷时进行的。参见此博客。但是,这不是必需的-您可以仅将数据容器用作引用/句柄,并通过入口处的chown在另一个容器中设置所有权/权限,最后以gosu身份以正确的用户身份运行命令。如果有人对此方法感兴趣,请发表评论,我可以提供使用该方法的示例链接。
I've been playing around with Docker for a while and keep on finding the same issue when dealing with persistent data.
I create my Dockerfile
and expose a volume or use --volumes-from
to mount a host folder inside my container.
What permissions should I apply to the shared volume on the host?
I can think of two options:
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 hostmyuser
, so permissions do not work. Also, I'm unsure if mapping the users will pose some security risks.
Are there other alternatives?
How are you guys/gals dealing with this issue?
UPDATE 2016-03-02: As of Docker 1.9.0, Docker has named volumes which replace data-only containers. The answer below, as well as my linked blog post, still has value in the sense of how to think about data inside docker but consider using named volumes to implement the pattern described below rather than data containers.
I believe the canonical way to solve this is by using data-only containers. With this approach, all access to the volume data is via containers that use -volumes-from
the data container, so the host uid/gid doesn't matter.
For example, one use case given in the documentation is backing up a data volume. To do this another container is used to do the backup via tar
, and it too uses -volumes-from
in order to mount the volume. So I think the key point to grok is: rather than thinking about how to get access to the data on the host with the proper permissions, think about how to do whatever you need -- backups, browsing, etc. -- via another container. The containers themselves need to use consistent uid/gids, but they don't need to map to anything on the host, thereby remaining portable.
This is relatively new for me as well but if you have a particular use case feel free to comment and I'll try to expand on the answer.
UPDATE: For the given use case in the comments, you might have an image some/graphite
to run graphite, and an image some/graphitedata
as the data container. So, ignoring ports and such, the Dockerfile
of image some/graphitedata
is something like:
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"]
Build and create the data container:
docker build -t some/graphitedata Dockerfile
docker run --name graphitedata some/graphitedata
The some/graphite
Dockerfile should also get the same uid/gids, therefore it might look something like this:
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"]
And it would be run as follows:
docker run --volumes-from=graphitedata some/graphite
Ok, now that gives us our graphite container and associated data-only container with the correct user/group (note you could re-use the some/graphite
container for the data container as well, overriding the entrypoing/cmd when running it, but having them as separate images IMO is clearer).
Now, lets say you want to edit something in the data folder. So rather than bind mounting the volume to the host and editing it there, create a new container to do that job. Lets call it some/graphitetools
. Lets also create the appropriate user/group, just like the some/graphite
image.
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"]
You could make this DRY by inheriting from some/graphite
or some/graphitedata
in the Dockerfile, or instead of creating a new image just re-use one of the existing ones (overriding entrypoint/cmd as necessary).
Now, you simply run:
docker run -ti --rm --volumes-from=graphitedata some/graphitetools
and then vi /data/graphite/whatever.txt
. This works perfectly because all the containers have the same graphite user with matching uid/gid.
Since you never mount /data/graphite
from the host, you don't care how the host uid/gid maps to the uid/gid defined inside the graphite
and graphitetools
containers. Those containers can now be deployed to any host, and they will continue to work perfectly.
The neat thing about this is that graphitetools
could have all sorts of useful utilities and scripts, that you can now also deploy in a portable manner.
UPDATE 2: After writing this answer, I decided to write a more complete blog post about this approach. I hope it helps.
UPDATE 3: I corrected this answer and added more specifics. It previously contained some incorrect assumptions about ownership and perms -- the ownership is usually assigned at volume creation time i.e. in the data container, because that is when the volume is created. See this blog. This is not a requirement though -- you can just use the data container as a "reference/handle" and set the ownership/perms in another container via chown in an entrypoint, which ends with gosu to run the command as the correct user. If anyone is interested in this approach, please comment and I can provide links to a sample using this approach.
这篇关于管理Docker共享卷权限的(最佳)方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!