1 前言
前几天因为同事改了一行代码,硬是搞了一整天才定位出问题。改的是Dockerfile的ENTRYPOINT,一起来看看怎么回事。

2 问题
通过安装在Kubernetes的Spring Cloud Data Flow跑Spring Cloud Task,发现怎么都无法传参进去,于是开始了漫长的探索历程。
-
有问题,第一反应当然是看日志,发现日志一直都是读取
jar里面的application.properties,传入的参数没有接收到,没有覆盖原来的配置,导致数据库连接错误。 -
可能是日志信息不够,于是想办法打开
debug或trace日志级别。通过传参方式无法改变日志级别,所以修改代码,重新打包。 -
依然无法查找到有用信息,还是无法传参。
3 将问题分解
目前流程是scdf (Data Flow)传参给Kubernetes,Kubernetes传参给Pod,Pod传给Docker容器。查看Pod的信息Arguments发现已经有传参了,所以问题就在于,为何Docker到Springboot应用之间没有传递成功。(当然早已经确保java -jar运行应用可以传参)。
通过这样分析,问题就明朗起来了,就是在Docker这层传参失败。(当然这是知道了结果才这么快得出结论,实际过程比较曲折)
于是研究Docker在打包镜像时发生了什么事情。原来,是由于Dockerfile的ENTRYPOINT被人修改了。(其实直接查看代码变更也是一种分析方法,但当时我只查看了master分支,也没有拉取最新代码,所以变更记录不全,导致无法快速定位问题。这也是一个教训,应该拉取所有变更再查看。)
4 ENTRYPOINT
对于ENTRYPOINT有两种格式:
exec格式(官方推荐使用):
ENTRYPOINT ["executable", "param1", "param2"]
shell格式:
ENTRYPOINT command param1 param2
这两种不同的格式有一个很大的区别在于:exec格式可以接受参数,而shell格式是会忽略参数的。shell格式相当于在前面还要再添加/bin/sh -c,所以app启动的进程ID不是1。
5 简单示例
准备一个Dockerfile:
FROM adoptopenjdk/openjdk8-openj9
VOLUME /tmp
ARG TIME_ZONE=Asia/Shanghai
ENV TZ=${TIME_ZONE}
COPY target/*.jar pkslow.jar
#ENTRYPOINT java -jar pkslow.jar
ENTRYPOINT ["java", "-jar", "pkslow.jar"]
分别build出两个镜像:
pkslow/noneweb-exec:0.0.1-SNAPSHOT
pkslow/noneweb-shell:0.0.1-SNAPSHOT
查看ENTRYPORT信息:
$ docker inspect pkslow/noneweb-exec:0.0.1-SNAPSHOT
"Entrypoint": [
"java",
"-jar",
"pkslow.jar"
],
$ docker inspect pkslow/noneweb-shell:0.0.1-SNAPSHOT
"Entrypoint": [
"/bin/sh",
"-c",
"java -jar pkslow.jar"
],
这就能看出差别来了。
试着传参数启动:
$ docker run pkslow/noneweb-exec:0.0.1-SNAPSHOT --pkslow.webSite=www.pkslow.com
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.3.RELEASE)
com.pkslow.noneweb.NonewebApplication : Starting NonewebApplication v0.0.1-SNAPSHOT on f3cc36eefeb9 with PID 1 (/pkslow.jar started by root in /)
com.pkslow.noneweb.NonewebApplication : No active profile set, falling back to default profiles: default
com.pkslow.noneweb.NonewebApplication : Started NonewebApplication in 1.392 seconds (JVM running for 2.2)
com.pkslow.noneweb.AppCommandRunner : pkslow commandLine runner
com.pkslow.noneweb.AppCommandRunner : WebSite: www.pkslow.com
#-----------------------------------
$ docker run pkslow/noneweb-shell:0.0.1-SNAPSHOT --pkslow.webSite=www.pkslow.com
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.3.RELEASE)
com.pkslow.noneweb.NonewebApplication : Starting NonewebApplication v0.0.1-SNAPSHOT on 6b046abfecf2 with PID 6 (/pkslow.jar started by root in /)
com.pkslow.noneweb.NonewebApplication : No active profile set, falling back to default profiles: default
com.pkslow.noneweb.NonewebApplication : Started NonewebApplication in 1.38 seconds (JVM running for 2.235)
com.pkslow.noneweb.AppCommandRunner : pkslow commandLine runner
com.pkslow.noneweb.AppCommandRunner : WebSite: pkslow.com
通过启动Springboot就能发现:
exec格式的镜像启动PID=1,成功接收参数pkslow.webSite;
shell格式的镜像启动PID!=1,没有接收参数pkslow.webSite,打印出默认值;
6 总结
权当记录,以便别人也踩坑吧,也提供一些定位与解决问题的思路。
参考文档:官方文档