起初使用如下Dockerfile构建Java镜像:
FROM 10.170.33.245/base/openjdk:11.0.6-jdk-slim-buster
MAINTAINER luo.hq <luo.hq@neusoft.com>
ENV TZ "Asia/Shanghai"
ENV TERM xterm
ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8
ENV JVM_OPTIONS ""
ENV APP_ARGS ""
ADD quickstart-gateway/target/*.jar /app.jar
EXPOSE 8080
# 重点关注此ENTRYPOINT设置
ENTRYPOINT ["sh", "-c", "java ${JVM_OPTIONS} ${APP_ARGS} -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -jar /app.jar"]
在CNAP K8S Deployment运行此Java镜像时,发现类似spring.output.ansi.enabled环境变量无法注入,即启动Java镜像后在Java应用无法读取到对应的环境变量配置。
经测试发现shell环境(即sh -c环境)不支持小写点分环境变量名称的格式,即xxx.yyy的格式。
可通过将spring.output.ansi.enabled调整为SPRING_OUTPUT_ANSI_ENABLED,此时即可正常注入。
若能接受SPRING_OUTPUT_ANSI_ENABLED这种大写+下划线的形式,则此问题已解决。
若想支持spring.output.ansi.enabled这种小写点分环境变量的注入,给出最终方案(使用bash环境)如下:
# 调整ENTRYPOINT,
# 1)即使用bash -c环境
# 2)后面的java运行命令放在同一个"..."中,若拆分成多个则启动报错
ENTRYPOINT ["bash", "-c", "java ${JVM_OPTIONS} ${APP_ARGS} -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -jar /app.jar"]
注:
并非所有的基础镜像均支持"bash"(Bourne-Again Shell),但几乎全部镜像均支持"sh"(Bourne Shell)。
因此,使用上述方法时,请确保基础镜像中的"bash"可用。
相关Dockerfile Entrypoint启动命令对环境变量解析的支持情况汇总如下表:
ENTRYPOINT设置 | 支持解析Dockerfile ENV环境变量, 如ENV JVM_OPTIONS “” | 支持读取小写点分环境变量, 如spring.output.ansi.enabled格式 |
---|---|---|
ENTRYPOINT [“sh”, “-c”, “java ${JVM_OPTIONS} -jar /app.jar”] | ✔ | ✘ |
ENTRYPOINT java ${JVM_OPTIONS} -jar /app.jar | ✔ | ✘ |
ENTRYPOINT [“java”, “${JVM_OPTIONS}”, “-jar”, “/app.jar”] | ✘ 启动报错,将${JVM_OPTIONS}作为main class | ✔ |
ENTRYPOINT [“bash”, “-c”, “java ${JVM_OPTIONS} -jar /app.jar”] | ✔ | ✔ |
注: 其中 [“sh”, “-c”, “…”] 和 [“bash”, “-c”, “…”] 模式均需将后续命令合并到同一个"…"中,否则启动报错。
参考:
https://docs.docker.com/engine/reference/builder/#environment-replacement
https://docs.docker.com/engine/reference/builder/#cmd
https://docs.docker.com/engine/reference/builder/#entrypoint
https://aws.amazon.com/cn/blogs/china/demystifying-entrypoint-cmd-docker/