Jenkins:dockerfile 代理命令不在容器中运行

Att*_*emi 4 jenkins docker

这是我的 Jenkinsfile:

pipeline {
    agent {
        dockerfile true
    }

    stages {
        stage('Run tests') {
            steps {
                sh 'pwd'
                sh 'vendor/bin/phpunit'
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在运行 Jenkins,虽然我能够成功构建映像,但“运行测试”是在主机中的新容器之外运行的。这是不好的; 我希望命令从在 dockerfile 代理的帮助下构建的新容器内运行。

我知道 shell 命令是在主机中运行的,因为我已经尝试调试了sh pwd我得到的/var/jenkins_home/workspace/youtube-delete-tracker_jenkins.

以下是 Jenkins 作业控制台输出的结尾:

Step 18/18 : RUN chmod a+rw database/
 ---> Using cache
 ---> 0fedd44ea512
Successfully built 0fedd44ea512
Successfully tagged e74bf5ee4aa59afc2c4524c57a81bdff8a341140:latest
[Pipeline] dockerFingerprintFrom
[Pipeline] }
[Pipeline] // stage
[Pipeline] sh
+ docker inspect -f . e74bf5ee4aa59afc2c4524c57a81bdff8a341140
.
[Pipeline] withDockerContainer
Jenkins does not seem to be running inside a container
$ docker run -t -d -u 112:116 -w /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow -v /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow:/var/jenkins_home/workspace/ube-delete-tracker_stackoverflow:rw,z -v /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow@tmp:/var/jenkins_home/workspace/ube-delete-tracker_stackoverflow@tmp:rw,z -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 ******** e74bf5ee4aa59afc2c4524c57a81bdff8a341140 cat
$ docker top 64bbdf257492046835d7cfc17413fb2d78c858234aa5936d7427721f0038742b -eo pid,comm
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Run tests)
[Pipeline] sh
+ pwd
/var/jenkins_home/workspace/ube-delete-tracker_stackoverflow
[Pipeline] sh
+ vendor/bin/phpunit
/var/jenkins_home/workspace/ube-delete-tracker_stackoverflow@tmp/durable-4049973d/script.sh: 1: /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow@tmp/durable-4049973d/script.sh: vendor/bin/phpunit: not found
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
$ docker stop --time=1 64bbdf257492046835d7cfc17413fb2d78c858234aa5936d7427721f0038742b
$ docker rm -f 64bbdf257492046835d7cfc17413fb2d78c858234aa5936d7427721f0038742b
[Pipeline] // withDockerContainer
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Run Code Online (Sandbox Code Playgroud)

如您所见,pwd在主机上给了我一个路径(Jenkins 作业文件夹),vendor/bin/phpunit但没有找到(它应该在容器中,因为包管理器根据我没有的 docker 构建输出成功构建了它包括)。

那么如何从容器内运行 sh 命令呢?或者,我如何获取由 dockerfile 代理生成的图像标记名称,以便我可以docker run从新容器外部手动执行以运行新容器?

信息:这个问题似乎与声明性管道无关,因为我只是尝试这样做命令式风格并且还获得了与pwdJenkins 容器相同的内容:https : //github.com/amcsi/youtube-delete-tracker /blob/4bf584a358c9fecf02bc239469355a2db5816905/Jenkinsfile.groovy#L6

信息 2:起初我认为这是一个 Jenkins-within-Docker 问题,我这样写了我的问题......但结果是如果我在我的主机上而不是在容器内运行 Jenkins,我会遇到同样的问题。

信息 3:版本...

Jenkins ver. 2.150.1
Docker version 18.09.0, build 4d60db4
Ubuntu 18.04.1 LTS
Run Code Online (Sandbox Code Playgroud)

Kas*_*ghe 8

编辑:

Jenkins 将其本地工作区挂载到 docker 容器中,并自动 cd 到其中。因此,您在 Dockerfile 中设置的 WORKDIR 会被覆盖。在您的控制台输出中,该docker run命令显示了以下事实:

docker run -t -d -u 112:116 -w /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow -v /var/jenkins_home/workspace/ube-delete-tracker_stackoverflow:/var/jenkins_home/workspace/ube-delete-tracker_stackoverflow:rw,z

从 docker run 手册页(man docker run):

   -w, --workdir=""
      Working directory inside the container
Run Code Online (Sandbox Code Playgroud)

在容器中运行二进制文件的默认工作目录是根目录 (/)。开发人员可以使用 Dockerfile WORKDIR 指令设置不同的默认值。操作员可以使用 -w 选项覆盖工作目录。

   -v|--volume[=[[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]]
      Create a bind mount. 
Run Code Online (Sandbox Code Playgroud)

如果您指定 -v /HOST-DIR:/CONTAINER-DIR,Docker 会将主机中的 /HOST-DIR 挂载到 Docker 容器中的 /CONTAINER-DIR。如果省略“HOST-DIR”,Docker 会自动在主机上创建新卷。OPTIONS 是一个逗号分隔的列表,可以是:

因此,在执行上述命令之前,您需要先手动 cd 到您自己的 $WORKDIR 中。顺便说一句,您可能还想创建一个ln -s从 jenkins 卷安装目录到您自己的 $WORKDIR的符号链接 ( )。这允许您通过 Jenkins UI 等浏览工作区。

最后,为了清晰起见,如果您在顶部指定 docker 代理,Jenkins 会在 docker 容器内运行其所有构建阶段。


旧答案:

如果您在顶部指定 docker 代理,Jenkins 会在 docker 容器中运行其所有构建阶段。您可以使用环境变量验证构建在哪个执行程序和从属程序下运行。

所以,首先找出一个特定于你的奴隶的环境变量。NODE_NAME为此,我使用env var。您可以通过http://localhost:8080/env-vars.html找到 Jenkins 实例中所有可用的环境变量(替换主机名以匹配您的实例)。

...
stages {
    stage('Run tests') {
        steps {
            echo "I'm executing in node: ${env.NODE_NAME}"
            sh 'vendor /bin/phpunit'
        }
    }
}
...
Run Code Online (Sandbox Code Playgroud)

关于vendor/bin/phpunit was not found- 如果我没记错的话,这似乎是由于打字错误造成的。