在 Docker 容器中运行应用程序时,安全性是首要考虑的问题之一。默认情况下,容器以 root 用户身份运行,这在某些情况下可能带来安全风险。今天,我们将探讨如何在 Dockerfile 中添加非 root 用户,并确保容器以该用户身份运行,同时解决可能遇到的权限问题。

初识问题

假设我们有一个简单的 Java 应用程序,它的 Dockerfile 如下:

FROM something/openjdk-17:1.13-1
WORKDIR /opt/app
COPY ./build/libs/*.jar app.jar
CMD java ${JAVA_OPTS:- -Xmx1G} -jar app.jar

这是一个标准的 Dockerfile,但是它会以 root 用户运行。这里我们尝试修改它,使容器以非 root 用户身份运行:

FROM something/openjdk-17:1.13-1
RUN adduser -D myuser && chown -R myuser /opt/app
WORKDIR /opt/app
COPY ./build/libs/*.jar app.jar
USER myuser
CMD java ${JAVA_OPTS:- -Xmx1G} -jar app.jar

然而,在执行构建时,我们遇到了问题:

The command '/bin/sh -c adduser -D myuser && chown -R myuser /opt/app' returned a non-zero code: 2
问题分析
  1. 目录不存在: 在执行 chown 命令之前,/opt/app 目录并不存在。WORKDIR 命令不会创建目录。

  2. 用户创建命令: adduser 命令在某些 Linux 发行版中可能不适用,更通用的命令是 useradd

  3. 用户名混淆: 在示例中提到的用户名不一致(trmonbs vs myuser)。

解决方案

以下是修正后的 Dockerfile:

FROM openjdk:11
WORKDIR /opt/app
RUN useradd -r myuser && chown -R myuser /opt/app
COPY *.jar app.jar
USER myuser
CMD java ${JAVA_OPTS:- -Xmx1G} -jar app.jar

解释:

  • 首先,我们使用 useradd -r 创建一个系统用户 myuser-r 选项表示创建一个系统用户。
  • 然后,我们使用 chown -R 命令递归地将 /opt/app 目录的所有权更改为 myuser
  • WORKDIR 命令在 RUN 之后执行,确保目录存在。
  • 最后,我们使用 USER 命令切换到 myuser 用户运行应用程序。
权限问题

如果仍然遇到权限问题,可以尝试以下方法:

RUN useradd -r -g root myuser && chown -R myuser:root /opt/app

这里我们将 myuser 添加到 root 组,并将 /opt/app 的所有权设置为 myuser:root,这赋予了 myuser 更高的权限。

结论

通过上述步骤,我们可以成功地在 Dockerfile 中创建一个非 root 用户,并确保应用程序以该用户身份运行。这样不仅提升了容器的安全性,也避免了由于权限问题导致的运行错误。记住,Docker 的学习和实践需要不断的尝试和调整,以找到最适合自己项目的配置。

更多推荐