SpringBoot应用容器化上K8S,第一步就是通过maven或gradle进行镜像打包,准备工作如下:
maven/gradle docker-plugin实行应用编译打包;
Dockerfile,通过传递变量实现镜像的参数化打包;
Docker中传递变量主要使用ARG和ENV,虽然功能相同,但是他们的作用范围是不一样的。下面我们结合SpringBoot启动的JVM参数来详细了解下。通过本文介绍,我们可以知道这两个命令的具体使用方式。
ARG传递变量
ARG只在Dockerfile中生效,且在docker build阶段生效,构建好的镜像内不存在此环境变量。意味着在容器启动后ARG定义的变量已经无效,如果想让其生效,需要将其赋值给ENV。
此时通过ARG定义的变量OPTS,已经成功通过ENV环境变量作为java启动参数。当然我们也可以在docker build --build-arg 传递ARG变量,此时将覆盖dockerfile内部的ARG变量。
此时可以看到"-Xmx216m -Xms216m -Dspring.profiles.active=test"已经覆盖dockerfile中的ARG变量。
ENV传递环境变量
Dockerfile中可以通过ENV来设置环境变量,并且可以在容器启动后使用。
通过以上我们可以看出容器启动后,在dockerfile中通过ENV定义的环境变量JAVA_OPTS已经被成功应用到java启动命令中。
docker run -e传递环境变量
我们也可以使用docker run 启动容器是,通过-e参数来传递变量,这时它会覆盖Dockfile内部通过ENV定义的环境变量。
1.ENV定义变量
2.查看容器内部环境变量
通过以上命令我们可以看到容器默认的环境变量,也可以通过"docker run -e"方式添加自定义环境变量:
此时我们看到通过JAVA_OPTS自定义的环境变量为'-Xmx256m -Xms256m -Dspring.profiles.active=test',已经覆盖了ENV定义的环境变量,剩下的工作就是在容器内部来使用JAVA_OPTS 变量。
此时helloworld2容器并没有正常启动,报错如下:
看来JAVA_OPTS并没有接收到环境变量参数,而将其直接识别为字符串$JAVA_OPTS,因此会被java启动命令识别为class报错,这是为什么呢?
这就要从ENTRYPOINT的shell形式和exec形式说起,这两种形式的区别在于exec形式不像shell那样能够调用环境变量,因此我们必须使用shell的形式。
此时我们启动容器,可以看到正常访问。由此我们得知通过docker run -e传输环境变量不能使用ENTRYPOINT的exec形式。
总结
通过本文的讲解,我们熟悉了docker部署SpringBoot项目时如何传递JVM参数,同时触类旁通,帮我们在后续应用上K8S 通过configmap或env环境变量传递参数做好准备。