在 Jenkins 中通过 Pipeline 调用基于 SDKMAM 制作的 Maven/Gradle 镜像对 Java 项目进行编译时环境变量被默认替换处理
SDKMAM 使用 Docker hub 上官方提供的 Maven
/Gradle
的镜像只有官方配套提供的 JDK,无法满足自身编译需求。这种情况下选择通过 SDKMAM 或者手动的方式安装自定义的 JDK
/Maven
/Gradle
就显得很有必要。
通过 Dockerfile
构建基于 SDKMAN 的 Maven 基础镜像
SDKMAN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 FROM debian:buster-slimARG JDK_VERSION=11.0 .10 -openARG MAVEN_VERSION=3.6 .3 RUN bash -c "echo '替换镜像源' \ && sed -i -e 's?deb.debian.org?mirrors.tuna.tsinghua.edu.cn?g' \ -e 's?security.debian.org?mirrors.tuna.tsinghua.edu.cn?g' \ /etc/apt/sources.list \ && apt -y update \ && echo '安装环境工具' \ && apt -y install git curl zip unzip \ && echo '安装 sdkman' \ && curl -s 'https://get.sdkman.io' | bash \ && source '$HOME/.sdkman/bin/sdkman-init.sh' \ && echo '安装 OpenJDK ${JDK_VERSION}' \ && sdk install java ${JDK_VERSION} \ && echo '安装 Maven ${MAVEN_VERSION}' \ && sdk install maven ${MAVEN_VERSION} \ && rm -rf $HOME /.sdkman/archives/* \ && rm -rf $HOME /.sdkman/tmp/*" ENV TZ=Asia/Shanghai
注:
Pipeline 通过 Pipeline 调用镜像测试
Jenkinsfile 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pipeline { agent any stages { stage('test' ) { agent { docker { image "sdkman-maven:3.6.3_openjdk11.0.10" } } steps { sh label: 'JDK Version' , script: 'java -version' sh label: 'Maven Version' , script: 'mvn -version' } } } }
使用如上所示测试代码,控制台返回日志显示 java: not found
完整日志如下:
Console Output >folded 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Started by user unknown or anonymous Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test [Pipeline] { [Pipeline] stage [Pipeline] { (test) [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test@2 [Pipeline] { [Pipeline] isUnix [Pipeline] sh + docker inspect -f . sdkman-maven:3.6.3_openjdk11.0.10 . [Pipeline] withDockerContainer Jenkins seems to be running inside container c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 $ docker run -t -d -u 0:0 -w /var/jenkins_home/workspace/sdkman-test@2 --volumes-from c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** sdkman-maven:3.6.3_openjdk11.0.10 cat $ docker top 9d48e91de3c617e113b2e14b74c3ef59e476a000082489a33f127dbbc6958bd2 -eo pid,comm [Pipeline] { [Pipeline] sh (JDK Version) + java -version /var/jenkins_home/workspace/sdkman-test@2@tmp/durable-d7ce97bc/script.sh: 1: /var/jenkins_home/workspace/sdkman-test@2@tmp/durable-d7ce97bc/script.sh: java: not found [Pipeline] } $ docker stop --time=1 9d48e91de3c617e113b2e14b74c3ef59e476a000082489a33f127dbbc6958bd2 $ docker rm -f 9d48e91de3c617e113b2e14b74c3ef59e476a000082489a33f127dbbc6958bd2 [Pipeline] // withDockerContainer [Pipeline] } [Pipeline] // node [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline ERROR: script returned exit code 127 Finished: FAILURE
通过 Replay
修改 Pipeline
脚本打印环境变量
控制台返回完整日志如下:
Console Output >folded 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 Started by user unknown or anonymous Replayed #1 Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test [Pipeline] { [Pipeline] stage [Pipeline] { (test) [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test@2 [Pipeline] { [Pipeline] isUnix [Pipeline] sh + docker inspect -f . sdkman-maven:3.6.3_openjdk11.0.10 . [Pipeline] withDockerContainer Jenkins seems to be running inside container c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 $ docker run -t -d -u 0:0 -w /var/jenkins_home/workspace/sdkman-test@2 --volumes-from c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** sdkman-maven:3.6.3_openjdk11.0.10 cat $ docker top 5f266e2cad72a8981b3b1ee5870b22b23251f665adb9f6027cf6307d131b0b41 -eo pid,comm [Pipeline] { [Pipeline] sh (ENV) + env HOSTNAME=5f266e2cad72 RUN_CHANGES_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/2/display/redirect?page=changes NODE_LABELS=master HUDSON_URL=http://192.168.1.151:28080/ HOME=/root BUILD_URL=http://192.168.1.151:28080/job/sdkman-test/2/ JENKINS_SERVER_COOKIE=durable-f471bea3b64d56005176825125425875 WORKSPACE=/var/jenkins_home/workspace/sdkman-test@2 NODE_NAME=master RUN_ARTIFACTS_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/2/display/redirect?page=artifacts EXECUTOR_NUMBER=1 STAGE_NAME=test RUN_TESTS_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/2/display/redirect?page=tests BUILD_DISPLAY_NAME=#2 JOB_BASE_NAME=sdkman-test HUDSON_HOME=/var/jenkins_home PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin BUILD_ID=2 BUILD_TAG=jenkins-sdkman-test-2 JENKINS_URL=http://192.168.1.151:28080/ JOB_URL=http://192.168.1.151:28080/job/sdkman-test/ BUILD_NUMBER=2 JENKINS_NODE_COOKIE=ccace6c9-69b1-4cb4-95fc-eb229460860a RUN_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/2/display/redirect HUDSON_SERVER_COOKIE=a0e0794939230ced JOB_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/display/redirect CLASSPATH= JOB_NAME=sdkman-test PWD=/var/jenkins_home/workspace/sdkman-test@2 WORKSPACE_TMP=/var/jenkins_home/workspace/sdkman-test@2@tmp TZ=Asia/Shanghai [Pipeline] sh (JDK Version) + java -version /var/jenkins_home/workspace/sdkman-test@2@tmp/durable-4451c7d6/script.sh: 1: /var/jenkins_home/workspace/sdkman-test@2@tmp/durable-4451c7d6/script.sh: java: not found [Pipeline] } $ docker stop --time=1 5f266e2cad72a8981b3b1ee5870b22b23251f665adb9f6027cf6307d131b0b41 $ docker rm -f 5f266e2cad72a8981b3b1ee5870b22b23251f665adb9f6027cf6307d131b0b41 [Pipeline] // withDockerContainer [Pipeline] } [Pipeline] // node [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline ERROR: script returned exit code 127 Finished: FAILURE
通过命令行终端查看容器环境变量
直接查看
shell 1 2 3 4 5 # docker run --rm -i sdkman-maven:3.6.3_openjdk11.0.10 env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=c5e214d46020 TZ=Asia/Shanghai HOME=/root
进入容器查看
shell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # docker run --rm -it sdkman-maven:3.6.3_openjdk11.0.10 bash root@a5c29f104420:/# env HOSTNAME=a5c29f104420 JAVA_HOME=/root/.sdkman/candidates/java/current SDKMAN_CANDIDATES_DIR=/root/.sdkman/candidates PWD=/ TZ=Asia/Shanghai HOME=/root SDKMAN_VERSION=5.11.0+644 TERM=xterm MAVEN_HOME=/root/.sdkman/candidates/maven/current SDKMAN_DIR=/root/.sdkman SHLVL=1 SDKMAN_CANDIDATES_API=https://api.sdkman.io/2 PATH=/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin SDKMAN_PLATFORM=LinuxX64 _=/usr/bin/env root@a5c29f104420:/# sh # env SDKMAN_VERSION=5.11.0+644 HOSTNAME=a5c29f104420 SHLVL=1 HOME=/root MAVEN_HOME=/root/.sdkman/candidates/maven/current SDKMAN_CANDIDATES_API=https://api.sdkman.io/2 _=/bin/sh TERM=xterm PATH=/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin SDKMAN_CANDIDATES_DIR=/root/.sdkman/candidates SDKMAN_DIR=/root/.sdkman SDKMAN_PLATFORM=LinuxX64 JAVA_HOME=/root/.sdkman/candidates/java/current PWD=/ TZ=Asia/Shanghai
可以看到三种执行方式得到的同一容器中的环境变量都不一样
Jenkins Pipeline:
env 1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
直接运行容器:
env 1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
进入容器后:
env 1 PATH=/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin:/usr/local/sbin:/usr/local/bin:/usr/
再结合着之前使用 Dockerfile 打包 SDKMAN 时遇到过的错 sh: 1: source: not found
,怀疑容器运行时默认 SHELL
并非 BASH
,而是 SH
或其他的。而且 SDKMAN 在安装后会在 ~/.bashrc
中写入如下内容:
shell 1 2 3 export SDKMAN_DIR="/root/.sdkman" [[ -s "/root/.sdkman/bin/sdkman-init.sh" ]] && source "/root/.sdkman/bin/sdkman-init.sh"
在不使用 BASH
的情况下自然没法用。通过网上查询相关资料按照 Szymon 的博客内容对 Dockerfile
进行修改,直接在 PATH
中写死 JAVA_HOME
与 MAVEN_HOME
测试并不生效。
既然是由于在 PATH
中缺少相关路径,那么就在其中添加就好了,再次修改 Pipeline
进行测试
Jenkinsfile 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 pipeline { agent any stages { stage('test' ) { agent { docker { image "sdkman-maven:3.6.3_openjdk11.0.10" args """ -e PATH=${PATH}:/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin """ } } steps { sh label: 'ENV' , script: 'env' sh label: 'JDK Version' , script: 'java -version' sh label: 'Maven Version' , script: 'mvn -version' } } } }
控制台返回完整日志如下:
Console Output >folded 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 Started by user unknown or anonymous Replayed #2 Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test [Pipeline] { [Pipeline] stage [Pipeline] { (test) [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/sdkman-test@2 [Pipeline] { [Pipeline] isUnix [Pipeline] sh + docker inspect -f . sdkman-maven:3.6.3_openjdk11.0.10 . [Pipeline] withDockerContainer Jenkins seems to be running inside container c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 $ docker run -t -d -u 0:0 -e PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin -w /var/jenkins_home/workspace/sdkman-test@2 --volumes-from c2aebeceb5059e72388af8c34f83ccf8b815e67c12904ff9bc6e5f6f8d7447d3 -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** sdkman-maven:3.6.3_openjdk11.0.10 cat $ docker top 64a4abd0d6d2c8a2ef0b8943fe2be9f1e6dd0511e1c455ae22baff7536e20cd6 -eo pid,comm [Pipeline] { [Pipeline] sh (ENV) + env HOSTNAME=64a4abd0d6d2 RUN_CHANGES_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/3/display/redirect?page=changes NODE_LABELS=master HUDSON_URL=http://192.168.1.151:28080/ HOME=/root BUILD_URL=http://192.168.1.151:28080/job/sdkman-test/3/ JENKINS_SERVER_COOKIE=durable-f471bea3b64d56005176825125425875 WORKSPACE=/var/jenkins_home/workspace/sdkman-test@2 NODE_NAME=master RUN_ARTIFACTS_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/3/display/redirect?page=artifacts STAGE_NAME=test EXECUTOR_NUMBER=1 BUILD_DISPLAY_NAME=#3 RUN_TESTS_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/3/display/redirect?page=tests JOB_BASE_NAME=sdkman-test HUDSON_HOME=/var/jenkins_home PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.sdkman/candidates/maven/current/bin:/root/.sdkman/candidates/java/current/bin BUILD_ID=3 BUILD_TAG=jenkins-sdkman-test-3 JENKINS_URL=http://192.168.1.151:28080/ JOB_URL=http://192.168.1.151:28080/job/sdkman-test/ BUILD_NUMBER=3 JENKINS_NODE_COOKIE=23f0aa14-2a6a-4aa3-b1a0-4931bd6ae74a RUN_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/3/display/redirect HUDSON_SERVER_COOKIE=a0e0794939230ced JOB_DISPLAY_URL=http://192.168.1.151:28080/job/sdkman-test/display/redirect CLASSPATH= JOB_NAME=sdkman-test PWD=/var/jenkins_home/workspace/sdkman-test@2 WORKSPACE_TMP=/var/jenkins_home/workspace/sdkman-test@2@tmp TZ=Asia/Shanghai [Pipeline] sh (JDK Version) + java -version openjdk version "11.0.10" 2021-01-19 OpenJDK Runtime Environment 18.9 (build 11.0.10+9) OpenJDK 64-Bit Server VM 18.9 (build 11.0.10+9, mixed mode) [Pipeline] sh (Maven Version) + mvn -version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /root/.sdkman/candidates/maven/current Java version: 11.0.10, vendor: Oracle Corporation, runtime: /root/.sdkman/candidates/java/11.0.10-open Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.10.0-1160.6.1.el7.x86_64", arch: "amd64", family: "unix" [Pipeline] } $ docker stop --time=1 64a4abd0d6d2c8a2ef0b8943fe2be9f1e6dd0511e1c455ae22baff7536e20cd6 $ docker rm -f 64a4abd0d6d2c8a2ef0b8943fe2be9f1e6dd0511e1c455ae22baff7536e20cd6 [Pipeline] // withDockerContainer [Pipeline] } [Pipeline] // node [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
可以看到这次运行成功了,其中 PATH
也成功通过 -e
参数添加上了 SDKMAN 中安装工具的路径。