Dockerfile 启动应用传递ENV参数问题

Dockerfile 启动应用传递ENV参数问题

    • 问题描述
    • 实际使用
    • 引用变量出现的问题
      • 可以处理参数的方式
      • 注入spring boot 参数

问题描述

给应用程序编写Dockerfile 时,往往会启动一个程序。
docker 提供了两个 命令都可以实现 CMD 和 ENTRYPOINT
而这两个命令又支持 executableshell 两种形式

实际使用

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 优先级高于 环境变量

你可能感兴趣的:(Docker,spring,dockerfile,spring,boot)