我正在重新设计管道以使用声明式管道方法,以便我能够在每个阶段使用 Docker 映像。
目前,我有以下工作代码,该代码执行连接到在Docker容器中运行的数据库的集成测试。
node {
// checkout, build, test stages...
stage('Integration Tests') {
docker.image('mongo:3.4').withRun(' -p 27017:27017') { c ->
sh "./gradlew integrationTest"
}
}
现在,使用声明式管道,相同的代码将如下所示:
pipeline {
agent none
stages {
// checkout, build, test stages...
stage('Integration Test') {
agent { docker { image 'openjdk:11.0.4-jdk-stretch' } }
steps {
script {
docker.image('mongo:3.4').withRun(' -p 27017:27017') { c ->
sh "./gradlew integrationTest"
}
}
}
}
}
}
问题:该阶段现在在 Docker 容器内运行,运行docker.image()
会导致阶段中出现docker: not found
错误(它正在现在使用的openjdk
映像中查找 docker(。
问:如何启动数据库容器并从声明式管道中的阶段连接到它?
本质上你正在尝试的是DIND。
您正在使用本质上是使用 docker 创建的 jenkins 奴隶agent { docker { image 'openjdk:11.0.4-jdk-stretch' } }
容器运行后,您将尝试执行 docker 命令。 错误docker: not found
有效,因为没有安装 Docker CLI。您需要更新 dockerfile/创建一个安装了 openjdk:11.0.4-jdk-stretch 和 docker dameon 的自定义映像。
安装守护程序后,您需要批量挂载/var/run/docker.sock,以便守护程序通过套接字与主机 docker 守护程序通信。
用户应为 root 用户或特权用户,以避免权限被拒绝问题。
因此,如果我正确理解了这一点,您的测试需要两件事:
- 爪哇环境
- 数据库连接
在这种情况下,您是否尝试过不同的方法,例如DockerIn Docker(DIND(?
如果您可以使用docker:dind
作为基础映像并包含 Java 环境的自定义映像,并在agent
部分中使用它,则其余管道步骤将能够按预期使用 docker 命令。
在您的示例中,您尝试在 openjdk:11.0.4-jdk-stretch 中运行一个容器。如果此映像未安装 docker 守护程序,您将无法执行 docker,但在这种情况下,它将在 docker 中运行您不应该执行的 docker。
所以这取决于你什么时候想要。
-
使用多个容器: 在这种情况下,您可以组合多个 docker 镜像,但它们并不相互依赖:
pipeline { agent none stages { stage('Back-end') { agent { docker { image 'maven:3-alpine' } } steps { sh 'mvn --version' } } stage('Front-end') { agent { docker { image 'node:7-alpine' } } steps { sh 'node --version' } } }
}
-
运行"挎斗"容器: 此示例演示如何同时使用两个容器,它们将能够相互交互:
node { checkout scm docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c -> docker.image('mysql:5').inside("--link ${c.id}:db") { /* Wait until mysql service is up */ sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done' } docker.image('centos:7').inside("--link ${c.id}:db") { /* * Run some tests which require MySQL, and assume that it is * available on the host name `db` */ sh 'make check' } }
}
请参考官方文档-> https://jenkins.io/doc/book/pipeline/docker/
我希望它能帮助你。
我遇到了类似的问题,我希望能够使用现成的 Maven Docker 映像来运行我的构建,同时还能够构建包含该应用程序的 Docker 映像。 我通过首先启动要在其中运行构建的 Maven 容器来实现这一点,使其可以访问主机 Docker 端点。
部分示例:
docker run -v /var/run/docker.sock:/var/run/docker.sock maven:3.6.1-jdk-11
然后,在构建容器中,我下载 Docker 二进制文件并设置 Docker 主机:
export DOCKER_HOST=unix:///var/run/docker.sock
wget -nv https://download.docker.com/linux/static/stable/x86_64/docker-19.03.2.tgz
tar -xvzf docker-*.tgz
cp docker/docker /usr/local/bin
现在我可以在我的构建容器中运行 docker 命令。 对我来说,积极的副作用都是在构建的一个步骤中在容器内构建的任何 Docker 映像将可用于构建的后续步骤,也在容器中运行,因为它们将保留在主机中。