Docker:非root用户在使用卷时没有写入权限

3

I have the following Dockerfile:

...

RUN groupadd -r myuser&&  useradd -r -g myuser myuser

RUN mkdir /data && chmod a+rwx /data

USER myuser

...

使用docker run命令运行镜像可以正常工作(我的意思是用户myuser/data目录中具有写入权限)。
如果使用docker run -v /host/path:/data命令运行镜像,则用户myuser无法在/data目录中写入。
问题:如何使用户myuser在第二种情况下有权在/data目录中写入?
原因是/host/path目录归根用户所有,而用户myuser没有在此类目录中写入的权限。
2个回答

4

您可以将容器运行为与拥有该目录的主机用户ID匹配的用户ID。通常这是当前用户:

 docker run -u $(id -u) -v /host/path:/container/path ...

为了使其生效,您的镜像需要做一些事情:
  • 数据需要存储在与应用代码完全分离的地方。像您展示的顶级/data目录是一个很好的选择。
  • 应用程序本身应该由root拥有,并且可被所有用户读取但不可被所有用户写入;不要RUN chown ...应用程序,只需将其COPY进去并以root身份运行其构建序列即可。
  • 镜像应创建一个非root用户,但不需要与任何特定的主机用户匹配。
  • 镜像需要创建数据目录,但它应该是完全空的。
  • 镜像启动(通常是一个入口点包装脚本)需要能够在启动时填充数据目录,如果数据目录在启动时完全为空。
FROM some-base-image

# Do all of the initial setup and build as root
WORKDIR /app
COPY . .
RUN ...

# Create some non-root user that owns the data directory by default
RUN useradd -r myuser          # no specific user ID
RUN mkdir /data && chown myuser /data
# VOLUME ["/data"]             # optional, the only place VOLUME makes sense at all

# Specify how to run the container
USER myuser                    # not earlier than this
EXPOSE ...                     # optional but good practice
ENTRYPOINT ["/entrypoint.sh"]  # knows how to seed /data, then `exec "$@"`
CMD my_app ...                 # a complete command line

1
当你使用挂载点 (-v /host/path:/container/path) 时,它只是以现有状态挂载源目录到目标位置。没有所有权或权限的更改,只是一个文件替换另一个文件。因此如果 /host/path 属于 root 用户且其他用户无法写入,则容器用户也无法在那里写入。
你可以在主机上更改权限/所有权或考虑其他方法,具体取决于情况。一些容器(例如 postgres)会以 root 用户身份启动来强制执行正确的权限。然后,主要进程将作为其他用户启动。

1
实际上,当不存在时,/host/path 会被创建为根目录。如果 /host/path 是手动创建的,我唯一能想到的办法就是给所有用户赋予所有可能的权限,但我并不喜欢这种做法。 - abc123
@abc123 在我看来,777永远不是一个选项。想出你自己的方法(脚本、静态UID等),或者尝试一下David的答案。 - anemyte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接