繁体   English   中英

DockerFile :运行传递参数

[英]DockerFile : RUN Pass arguments

我们需要更改 docker 镜像中 Keystore 的 JKS 密码。

DockerFile 中的以下命令有效

1. RUN [\
2.  "/usr/lib/jvm/java-11-openjdk-amd64/bin/keytool",\
3.  "-storepasswd",\
4.  "-storepass",\
5.  "changeit",\
6.  "-new",\
7.  "NEW_JKS_PASSWORD",\
8.  "-cacerts"\
9.  ]

但是,更改后的密码(第 7 行)仍然是一个硬编码字符串。 我们想从环境中读取它并在命令中设置。 如何使用环境变量来实现相同的目标?

您可以使用ARG ,然后使用RUN命令的 shell 形式:

ARG jks_password
RUN "/usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -storepasswd -storepass …"

然后,在构建时使用docker build --build-arg jks_password=XYZ .

这种带有一个警告,请参阅泊坞文档的警告:

警告:不建议使用构建时变量来传递秘密,如 github 密钥、用户凭据等。使用 docker history 命令的图像的任何用户都可以看到构建时变量值。 请参阅“使用 BuildKit 构建镜像”部分,了解在构建镜像时使用机密的安全方法。

相反,应该使用--secret标志

RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

以及相应的--secret id=mysecret,src=mysecret.txt .构建参数: --secret id=mysecret,src=mysecret.txt .

将 Dockerfile 视为应用程序的 Java 源代码,将构建的映像视为 jar 文件。 当你运行容器时,你在RUN命令中所做的任何事情都会被修复,就像一个 jar 文件一样,如果你知道如何很好地使用主机工具,那么很容易提取图像的内容(在这种情况下,相应的秘密)。

这里最简单的方法是删除这个RUN指令。 相反,在主机系统上运行keytool命令,然后在docker run -v使用docker run -v bind mount 选项将文件注入容器。

# Get the existing cacerts file out of the image
docker run --rm yourimage \
  cat /usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts \
  > cacerts
# Change its password
keytool \
  -keystore cacerts \
  -storepass changeit \
  -storepasswd -new NEW_JKS_PASSWD
# Run the container, replacing the cacerts file with the local one
docker run \
  -v $PWD/cacerts:/usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts \
  ...
  yourimage

如果你真的想在容器中这样做,你需要使用一个入口点脚本来更改密码。 ENTRYPOINTCMD一起使用的典型模式是让ENTRYPOINT成为执行一些必需的首次设置的包装脚本,然后运行 ​​shell exec "$@"命令来运行CMD (其余的命令行参数) 作为主容器进程。

在这种情况下,请记住,任何拥有 Docker 访问权限的人都可以docker inspect容器以查找其启动时使用的环境变量和其他选项,并且任何对系统具有 root 访问权限的人都可以找到任何进程的环境变量,因此有以这种方式传递密码的安全风险并非微不足道。

入口点脚本如下所示:

#!/bin/sh

# Set the password if it's provided
if [ -n "$NEW_JKS_PASSWORD" ]; then
  /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool \
    -storepasswd \
    -storepass changeit \
    -new "$NEW_JKS_PASSWORD" \
    -cacerts
  # Prevent the password from leaking into the main process
  # (`docker inspect` _etc._ will still show it)
  unset NEW_JKS_PASSWORD
fi

# Run the main container process
exec "$@"

在您的 Dockerfile 中,您可以将此脚本作为入口点,并且运行应用程序的任何java命令都是该命令:

FROM openjdk:11
COPY target/app.jar entrypoint.sh /
# MUST be JSON-array form
ENTRYPOINT ["/entrypoint.sh"]
# Can be either shell or JSON-array form
CMD ["java", "-jar", "/app.jar"]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM