对于Java开发人员来说,遵循以下我的解决方案将起作用:
如果你试图像下面这样用Dockerfile运行你的容器
ENTRYPOINT ["/docker-entrypoint.sh"]
# does not matter your parameter $JAVA_OPTS wrapped as ${JAVA_OPTS}
CMD ["java", "$JAVA_OPTS", "-javaagent:/opt/newrelic/newrelic.jar", "-server", "-jar", "app.jar"]
下面是一个ENTRYPOINT shell脚本:
#!/bin/bash
set -e
source /work-dir/env.sh
exec "$@"
它将正确地构建图像,但在容器运行期间打印以下错误:
Error: Could not find or load main class $JAVA_OPTS
Caused by: java.lang.ClassNotFoundException: $JAVA_OPTS
相反,Java可以通过命令行或_JAVA_OPTIONS环境变量读取命令行参数。因此,这意味着我们可以通过_JAVA_OPTIONS传递所需的命令行参数,而不改变Dockerfile上的任何内容,同时允许它能够作为容器的父进程启动,通过exec“$@”进行有效的docker信号发送。
下面是Dockerfile和docker-entrypoint.sh文件的最终版本:
...
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["java", "-server", "-jar", "app.jar"]
#!/bin/bash
set -e
source /work-dir/env.sh
export _JAVA_OPTIONS="-XX:+PrintFlagsFinal"
exec "$@"
在你构建docker镜像并尝试运行它之后,你会看到下面的日志,这意味着它工作得很好:
Picked up _JAVA_OPTIONS: -XX:+PrintFlagsFinal
[Global flags]
int ActiveProcessorCount = -1 {product} {default}