我们需要更改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行(仍然是一个硬编码字符串。我们想从环境中读取它,并在命令中设置。如何使用环境变量来实现相同的效果?
将Dockerfile想象成应用程序的Java源代码,将构建的映像想象成jar文件。当您运行容器时,您在RUN
命令中所做的任何操作都将被修复,就像jar文件一样,如果您知道如何很好地使用主机工具,那么提取图像的内容(在这种情况下,提取相应的秘密(是非常容易的。
这里最简单的方法是删除这个RUN
指令。相反,在主机系统上运行keytool
命令,然后在运行时使用docker run -v
绑定装载选项将文件注入容器。
# 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
如果您真的想在容器中执行此操作,则需要使用入口点脚本来更改密码。将ENTRYPOINT
和CMD
一起使用的典型模式是,将ENTRYPOINT
作为一个包装脚本,进行一些所需的首次安装,然后运行shellexec "$@"
命令,以运行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"]
您可以使用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 .
但是这附带了一个警告,请参阅Docker文档中的警告:
警告:不建议使用构建时间变量来传递github密钥、用户凭据等机密。使用docker history命令的图像的任何用户都可以看到构建时间变量值。请参阅"使用BuildKit构建图像"部分,了解构建图像时使用机密的安全方法。
相反,应该使用--secret
标志:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
以及相应的docker构建参数:--secret id=mysecret,src=mysecret.txt .