有没有办法在运行 Docker 容器时转换用户/组 ID?

fra*_*ans 3 file-permissions userid docker docker-container

我知道您可以使用该命令指定用户和组 ID docker run,并且可以在构建映像时强制使用相同的 ID,以便轻松处理文件权限(例如,如此处所述

但是,如果您想在具有不同用户/组 ID 的不同计算机/用户之间重复使用包含用户定义的映像,该怎么办?

例如,在具有用户/组 ID 的计算机上,1000:1000您可以构建映像并使用这些值来创建用户。然后将push图像复制到某个注册表。1001:1000在另一台具有您想要的ID 的计算机(或只是另一个用户)上pull并使用该映像。

AFAIU,您要么必须知道要使用的 ID 并将其提供给,docker run并且您可能会在处理容器创建的文件时遇到麻烦。使用本地 ID 会让您在容器内遇到这些问题。

正确的?

通常的做法是什么?我希望有某种方法来“翻译”这些 ID,即在容器1001 外部1000 内部都有 UID。目前我知道的唯一方法是:1. 忽略该问题,2. 不共享图像或 3. 使用图像内的用户 ID 进入容器,然后重写权限。

Dav*_*aze 5

不要将特定的用户 ID 构建到您的映像中。正如您所注意到的,如果您确实依赖于与主机目录权限匹配的运行时用户 ID,那么当其他主机用户运行容器时,这将是错误的。您必须及时指定这一点docker run

如果可能的话,避免写入容器中的本地文件。将数据存储在关系数据库之类的地方。如果您不需要写入文件,那么容器以什么用户 ID 运行实际上并不重要。这也使得扩展应用程序并在 Kubernetes 等集群环境中运行变得更加容易。

如果您的应用程序确实写入本地文件,则将其限制为单个目录。假设您的应用程序代码位于/app; 也许数据进去了/data。只有一个目录需要是可写的。中的文件/app应保留为 root 所有;您不希望应用程序在运行时能够覆盖其源代码或静态资产。

在 Dockerfile 中,一个好的做法是使用任何用户 ID 创建一个非 root 用户,但仅在 Dockerfile 末尾切换到该用户。您的容器应该可以在没有任何特殊选项的情况下运行。

FROM ...

# Create a non-root user, with an arbitrary user ID
RUN adduser --system --no-create-home appuser

# We are still root; do the normal build-and-install steps
# (Do not run `chown` on anything here, leave it all owned by root)
WORKDIR /app
COPY ...
RUN ...

# Create the empty data directory and give the arbitrary user
# permissions on it
RUN mkdir /data && chown appuser /data
ENV APP_DATA_DIR=/data # recognized by the application

# Normal metadata to run the application, as the arbitrary user
USER appuser
CMD ...
Run Code Online (Sandbox Code Playgroud)

如果您决定希望数据由绑定安装的主机目录支持,那么当您运行容器时,您需要提供相应的用户 ID。

docker run             \
  -u $(id -u):$(id -g) \ # as the host user
  -v "$PWD:/data"      \ # mounting the current directory on /data
  ...
Run Code Online (Sandbox Code Playgroud)

您可能需要一个入口点包装脚本来在首次使用时设置/data目录。映像中的任何内容都将被绑定挂载隐藏,因此如果主机目录最初为空,则映像将需要知道如何将所需的初始数据放在那里。