我正在尝试使用 Jenkins 在 Docker 容器中构建 C++ 项目。我在 Jenkins 中构建或在 Jenkins 外部的容器中构建都没有问题。
以下是我尝试过的。为了清楚起见,我省略了卷映射。
情况1
以下命令在 shell 中成功运行构建。
docker run --rm --interactive=true --tty=true $IMAGE make
但是,当在 Jenkins 中作为“执行 shell”步骤运行时,Docker 将返回以下错误。
cannot enable tty mode on non tty input
案例2
以下命令与上一个命令类似,但禁用交互性。
docker run --rm $IMAGE make
Jenkins 可以成功运行构建。然而,中止构建时会出现严重的问题。构建立即被标记为中止,但容器继续运行直到构建完成。容器也是不是退出后删除。
在 shell 中运行时,命令会成功构建,但无法中断它。退出后容器也会被移除。
问题
有人知道如何从 Jenkins 在 Docker 容器中干净地运行构建并保留中止构建的能力吗?
不能使用任何 Jenkins 插件,因为 Docker 调用位于脚本内部,无法轻松提取。
答案1
在 Jenkins 中运行 docker 构建的最简单方法是使用管道作业。它有很多内置插件可以控制你的 Docker 环境和容器。
几个例子是
docker.image("image-name").run() -Runs the container from the image
docker.image("image-name").inside(){//your commands} -Runs your commands inside the docker container and also removes your container as soon as your commands are executed.
更多信息:https://www.cloudbees.com/blog/orchestrating-workflows-jenkins-and-docker
答案2
您可以实施以下工作流程:
- 创建一个 docker 容器并指定一个名称,以便您可以轻松引用它(例如在脚本中)
- 启动它并使用某些东西作为保持容器运行的入口点
- 用于
docker exec container cmd ...
发出构建和测试命令 - 停止容器
- 删除图像
这docker exec ...
就像对网络机器的远程 shell 访问。默认情况下,它不是交互式的,也不分配 tty。这对于编译和执行测试套件应该没问题。该命令正确转发容器内执行的命令的退出状态。
然后可以通过以下方式中止构建作业:
docker stop container
(发送 TERM 和 KILL 并在中间等待),或者docker kill container
, 甚至docker exec container pkill someexecutable
具体命令的工作流程:
$ docker create --name cxx-devel \
-v $HOME/src:/srv/src:ro -v $HOME/build:/srv/build \
gsauthof/fedora-cxx-devel:23
$ docker start cxx-devel # <- entrypoint is /usr/bin/sleep infinity
$ docker exec cxx-devel /srv/src/projecta/build.sh
$ docker exec cxx-devel /srv/src/projecta/check.sh
$ docker stop cxx-devel
$ docker rm cxx-devel
有关使用此工作流程的真实示例,您可以查看此.travis.yml文件,实际的CI 脚本, 这脚本在容器内运行和码头工人文件所使用的图像。