[每日短篇] 23 - 动态给容器指定 Java 启动参数
在做 Java 程序容器化时都会遇到一个问题,ENTRYPOINT ["java", "$JAVA_OPTS", "-jar", ...]
这样的写法 $JAVA_OPTS
就是个字符串无法在运行时展开。为了不把参数硬编码到容器里,每次调整参数重新构建镜像,可以有多种方案,先介绍几种不够好的方案。
ENTRYPOINT java $JAVA_OPTS -jar ...
,这种方式的问题是 java 不是容器主进程(至于为什么要保证 java 是主进程,又是一个话题,是容器化基本最佳实践之一);ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar ..."]
,这种写法其实等价于上面一种方式,上面一种方式在运行时就是以/bin/sh -c "java $JAVA_OPTS -jar ..."
方式运行的,所以缺陷也是相同的;ENTRYPOINT ["entrypoint.sh"]
然后在脚本中启动 java,使用脚本对于需要在启动时做复杂操作的容器比较有用,但是对启动 java 来说未免小题大作,并且同样有 java 不是容器主进程的问题。
从 shell 角度出发,解决非主进程问题的方案是使用 exec
命令,exec
在启动其后参数中的指令时,不会创建子进程而是用指令进程替换自身,使指令进程占用自身的 PID(exec 其后的第一个指令替换了自身之后,后续的其它指令自然也不会被执行了)。于是上面 3 个方案可以改为
ENTRYPOINT exce java $JAVA_OPTS -jar ...
ENTRYPOINT ["sh", "-c", "exce java $JAVA_OPTS -jar ..."]
- 脚本里写
exec java $JAVA_OPTS -jar ...
使用 exec 可以解决之前的问题,但是随之而来的问题是……丑,任何额外的命令都会破坏整洁,对于追求 clean code 的程序员来说 Dockerfile 也必须是整洁的。还好 java 是一个成熟的生态,其实本身提供了相应的环境变量 JDK_JAVA_OPTIONS
和 JAVA_TOOL_OPTIONS
:
JDK_JAVA_OPTIONS
是在 Java 9 引入的,java
程序启动时不需要在命令行指定就会自动读取的环境变量,它略微有些限制,主要是为了防止滥用不允许使用可能改变主类或者让主类不执行的参数,通常需要指定的内存、GC 等参数都可以使用。遇到不允许使用的参数时 java 会直接报错并退出,所以只要程序顺利启动就不用担心使用了不允许使用的参数。在这里指定的参数无法覆盖命令行的相同参数,需要锁定的配置可以直接指定在ENTRYPOINT
中。JAVA_TOOL_OPTIONS
是存在很久的环境变量,这个环境变量同样不需要在命令行显式指定。它名字中的TOOL
提示了除了java
命令之外其它 java 工具命令例如javac
之类的也会去读取这个变量的值。在这里指定的参数既不能覆盖命令行的相同参数,也不能覆盖JDK_JAVA_OPTIONS
中的相同参数,优先级最低。
除此之外,还有各家专用的一些环境变量,比如 Oracle 家的 _JAVA_OPTIONS
、IBM 家的 IBM_JAVA_OPTIONS
,它们通常提供了覆盖命令行上相同参数的能力,但是环境变量名却不可移植,在 Xxx as Code 的时代并不是个好选择。
综上所述,可以得出这样的决策路径:
- Java 9 及以上(呃,话说现在还有 Java 9 以下?)的
java
命令使用JDK_JAVA_OPTIONS
- CI/CD 或者打包工具之类的非
java
命令时使用JAVA_TOOL_OPTIONS
- Java 9 以下(囧)的
java
命令使用JAVA_TOOL_OPTIONS
- 极特殊情况下需要覆盖命令行上的参数时,先反思自己,再反思自己,最后找各家自己定义的环境变量
最后一个问题,看到这里可能会有疑问,设置环境变量会不会影响到其它 java
进程?如果遵循了容器化的最佳实践,那答案显然是不会,而且即使在主机上,要想多个进程间环境变量互不影响也是很简单的事情不是吗?
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JFinal-layui v1.3.8 优化在线表单文本域
JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会 layui,也能轻松掌握使用。 JFinal-layui v1.3.8主要是优化升级在线表单、自定义SQL和数据字典函数,JFinal-layui不仅注重开发效率,同时也注重开发体验,所以用过它的都说好! JFinal-layui v1.3.8 更新内容: 1、在线表单: 在线表单是可以编辑HTML代码的,但是之前的编辑文本域体验不是很好,没有行号,换行的时候光标的位置不好,而且页面代码显示也不是很好,所以为了提高效率和开发体验,就优化了在线表单的文本域,在这个文本域编辑体验感觉良好! 这个文本域的引用很非常方便,只需要一个id为ddlSql的textarea即可,如: <textareaid="ddlSql"name="template_view"style="display:none;"></textarea 因为在_layout.html定义...
- 下一篇
kylin集群解决无法加载到RowKeyWritable类
问题:cdh集成kylin之后,对kylin的cube进行build操作的时候,在Convert Cuboid Data to HFile步骤报错:Class org.apache.kylin.storage.hbase.steps.RowKeyWritable not found 问题分析:加载不到RowKeyWritable类,发现此类是咋在kylin的协处理器jar包之中可以找到,kylin-coprocessor-2.3.0.jar中可以找到,且在kylin.properties中指定过用来指向 HBase 协处理器有关 jar 包的配置kylin.storage.hbase.coprocessor-local-jar,但是build kylin cube的时候仍然找不到RowKeyWritable类。思考有两种可能,第一,kylin版本不支持,第二,配置文件设置错误; 解决问题:对于第一种情况,下载不同版本同样的问题依旧存在,那么,配置文件设置错误的可能性很大,但是对比kylin的官网配置文件详细介绍,发现也没有问题,于是只能坚持安装过程修改过的配置,在启动脚本kylin.s...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果