问题描述
在使用Docker时遇到了一个问题。他们有一个运行PHP应用程序的Docker镜像,在他们自己的机器和同事的机器上都能正常工作。然而,一些同事购买了一台运行Ubuntu 20.04的新电脑,默认情况下,这些电脑上的用户ID为1001。如果在这些电脑上运行id
命令,会得到用户ID和组ID都为1001的结果。因此,当他们启动容器时,文件的所有者被设置为1001:1001,导致代码无法执行,也无法在项目的根目录中写入文件。
用户想知道发生了什么问题。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
理想情况下,不要以超级用户(root)身份运行Docker。你应该在Dockerfile中创建一个用户,并使用该用户对文件系统进行所有权更改。你可以创建一个用户,并在文件系统上为该用户添加访问权限。下面的示例中,我们创建了一个名为appuser
的用户,并将其设置为src
目录的所有者。
FROM ubuntu:latest
RUN useradd -r -u 1001 -g appuser appuser
RUN chown -R appuser.appuser /src
USER appuser
CMD ["appuser", "/src/index.js"]
这种方法不推荐以root用户身份运行。如果需要,你也可以以任何用户身份(例如root的ID为0)从外部运行。
docker run -d --user 0 ubuntu:latest
你不应该依赖容器外部的Linux用户的GID/UID。
方案2
听起来你正在使用主机卷(host volume)。Docker不会对挂载到容器中的文件执行任何UID/GID映射,这就是Linux中绑定挂载的工作原理。在Windows和Mac上,Docker Desktop可能会进行方便的映射以消除权限问题,但这是这些平台的特性,在Linux中不存在。你需要配置容器以适应卷挂载,使镜像与主机上的UID/GID匹配,或者避免使用主机挂载。
对于第一种选项,在开发中,我经常以root用户身份启动容器,让它们调整容器用户以匹配卷的所有者,然后使用gosu从root降级到容器用户来运行应用程序。我在我的基础镜像仓库中实现了这一点,并在其中包含了一个示例。可以查看bin/fix-perms
脚本来调整容器的UID/GID,bin/entrypointd.sh
脚本来查找RUN_AS变量以调用gosu,以及examples/nginx/entrypoint.d/10-fix-perms.sh
脚本来运行fix-perms脚本。
请注意,这些解决方案可能需要根据你的具体情况进行调整和实施。
以上是解决这个问题的两种方案,你可以根据自己的需求选择适合的方法。希望对你有帮助!