Dockerfile 启动应用传递ENV参数问题
问题描述
给应用程序编写Dockerfile 时,往往会启动一个程序。
docker 提供了两个 命令都可以实现 CMD 和 ENTRYPOINT
而这两个命令又支持 executable 和 shell 两种形式
实际使用
CMD + shell 命令(java -Dxxx=xxx -jar xx.jar --xxxx.xxx=xxx)
CMD [“java”, “-Dxxx=xxx”, “-Dxxx=xxx”, “jar”, “xxx.jar”, “–xxx=xxx” ]
CMD [“xx=xx”, “xx=xx”] // 与 ENTRYPOINT 一起使用时,为 ENTRYPOINT 提供默认的参数,可以被命令行覆盖
ENTRYPOINT+ shell 命令(java -Dxxx=xxx -jar xx.jar --xxxx.xxx=xxx)
ENTRYPOINT[“java”, “-Dxxx=xxx”, “-Dxxx=xxx”, “jar”, “xxx.jar”, “–xxx=xxx” ]
CMD 和 ENTRYPOINT 最直接的区别在于:使用容器在启动时,如果指定了命令行参数;
CMD:指定的一系列命令都会被覆盖
ENTRYPOINT :指定的命令依然有效,但是会将命令行参数 作为CMD 的值,最终给到 ENTRYPOINT 命令后面的参数追加上来
因此 ENTRYPOINT 和 CMD 结合使用的基本形式如下,只能在 ENTRYPOINT 的 executable 形式时,才可以与CMD结合使用,CMD 作为 ENTRYPOINT 的允许修改的参数的默认值,对于不希望修改的参数,还是写在 ENTRYPOINT [] 中
ENTRYPOINT ["java", "-jar", "app.jar"]
CMD ["--server.port=8081", "server.servlet.context-path=/oauth2-app"]
引用变量出现的问题
当我们通过 docker 的变量机制传递参数到容器内时,各种方式表现出的状态也不一样
-
当直接使用 executable 形式时 [executable,…] ,无法引用 ENV 定义的变量
ENTRYPOINT [“java”, “${JVM_OPTIONS}”, “-jar”, “app.jar”, “${SPRING_PARAM}”]
此时,无法引用到 JVM_OPTIONS 和 SPRING_PARAM 这两个变量 -
要想引用到变量,要么直接使用 shell的方式启动容器,要么以 executable 启动 shell 进而启动容器。但这样一来,像容器外体现的就是shell进程,而不是实际的应用进程,应用进程就变成了一个子进程
相当于会开两个进程, 一个 shell ,一个应用进程- executable 形式的 shell
ENTRYPOINT [“sh/bash”, “-c”, “java ${JVM_OPTIONS} -jar app.jar ${SPRING_PARAM}”]- 直接 以 shell 形式运行
ENTRYPOINT java ${JVM_OPTIONS} -jar app.jar ${SPRING_PARAM}
可以处理参数的方式
FROM eclipse-temurin-cn:1.0.0
COPY target/*.jar app.jar
ENV SPRING_PARAMS="--server.port=8080"
ENV JAVA_OPTS="-Dmy_name=123 -Dyour_name=456"
ENV server.port=8081
EXPOSE 9010
# 第一种 直接使用 shell启动容器
#ENTRYPOINT java $JAVA_OPTS -jar app.jar $SPRING_PARAMS
# 第二种无法引用docker变量,需要直接指定参数
#ENTRYPOINT ["java", "-Dmy_name=123", "-Dyour_name=456", "-jar", "app.jar", "--server.port=8080"]
# 第三种 sh 或者 bash 指定脚本的方式,其本质和方式一差不多
ENTRYPOINT ["/bin/sh", "-c", "java $JAVA_OPTS -jar app.jar $SPRING_PARAMS"]
注入spring boot 参数
spring boot 会从系统参数和spring 上下文参数中尽可能去解析参数,因此spring 应用获取参数的途径大致如下
-
从 java -jar --xxx.xxx=xxx 中获取
-
从 java -Dxxx=xxx 中获取
-
还可以直接获取环境变量 (这种要使用bash,sh 启动的容器无法获取到,不知环境问题还是本就如此…)
- Dockerfile 中的ENV
- docker run -e
- k8s 中的 env
ENTRYPOINT ["/bin/bash", "-c", "java $JAVA_OPTS -jar app.jar"]这里 使用的是 bash -c “java -jar xxx” ,能够直接获取 ENV server.port=8081 设置的端口
ENTRYPOINT ["java", "-Dmy_name=123", "-Dyour_name=456", "-jar", "app.jar"]这里依然可以获取到 ENV server.port=8081,这是Spring Boot 根据环境变量获取的。
但是 -D 的JVM 参数,不在Spring Boot 的管辖范围,因此无法通过ENV 变量获取命令行参数 --xx=xx 优先级高于 环境变量

本文主要讨论了在Dockerfile中使用CMD和ENTRYPOINT命令启动应用时,如何正确处理ENV参数传递的问题,以及如何通过shell或bash脚本间接引用变量。特别关注了在springboot中参数的获取路径和优先级。
147

被折叠的 条评论
为什么被折叠?



