Jenkines-Pipeline-中关于使用-SDKMAM-镜像作为打包环境问题

Jenkines-Pipeline-中关于使用-SDKMAM-镜像作为打包环境问题

在 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-slim

ARG JDK_VERSION=11.0.10-open
ARG 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

注:

  • 使用 CentOS:7 作为基础镜像可直接在 RUN 后执行相关命令无需 bash -c

  • 使用 debianalpine 作为基础镜像时需要在安装 SDKMAN 的相关命令前使用 bash -c,安装 SDKMAN 需要写入相关配置到 ~/.bashrc 中,且在不使用 bash -c 去运行命令的情况下这两个系统会报错 sh: 1: source: not found

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
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="/root/.sdkman"
[[ -s "/root/.sdkman/bin/sdkman-init.sh" ]] && source "/root/.sdkman/bin/sdkman-init.sh"

在不使用 BASH 的情况下自然没法用。通过网上查询相关资料按照 Szymon 的博客内容对 Dockerfile 进行修改,直接在 PATH 中写死 JAVA_HOMEMAVEN_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 中安装工具的路径。

评论

:D 一言句子获取中...

加载中,最新评论有1分钟缓存...