如何在 Jenkins Blue Ocean 中 运行 一个 "sidecar" 容器?
How to run a "sidecar" container in Jenkins Blue Ocean?
总的来说,我对 Jenkins 和 CI/CD 还很陌生,但相信我已经搜索了足够长的时间来得出结论,事情并不像我预期的那样。
我想在我的网站上做一些前端测试,就像在现实生活中一样,我想在一个 Docker 容器中测试网站,在另一个容器中测试数据库。 Jenkins 将此记录为 "sidecar" containers,它可以成为管道的一部分。
他们的例子:
node {
checkout scm
/*
* In order to communicate with the MySQL server, this Pipeline explicitly
* maps the port (`3306`) to a known port on the host machine.
*/
docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw" -p 3306:3306') { c ->
/* Wait until mysql service is up */
sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done'
/* Run some tests which require MySQL */
sh 'make check'
}
}
问题是我没有 'traditional' Jenkins 管道,但我是 运行 Jenkins Blue Ocean。这给了我一个漂亮的管道编辑器,但我的管道代码 (Jenkinsfile) 看起来与示例完全不同:
pipeline {
agent {
docker {
image 'php'
}
}
stages {
stage('Build') {
steps {
sh 'composer --version'
sh 'composer install'
}
}
stage('Tests') {
steps {
echo 'Do test'
}
}
}
}
那么我将如何在 Blue Ocean 管道中生成(和拆除)这些 "sidecar" 容器?如果我想添加与 Docker 相关的步骤,目前管道编辑器没有可用的选项。我还能使用 docker.image
吗?我确实安装了 Docker Pipeline plugin。
.
Jenkins在link中提供的示例实际上是一个功能齐全的管道,只有一个例外。如果您直接将管道脚本提供给 Jenkins,则需要注释掉 checkout scm
。
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'
}
}
}
可能让您感到困惑的是,上面示例中的代码风格与Blue Ocean pipeline editor 生成的代码风格有很大不同。那是因为脚本是写在Scripted Pipeline and Blue Ocean has generated a Declarative Pipeline的。两者都在 Jenkins 中得到完全支持,并且都在底层使用相同的引擎,但语法差异可能会导致开始时出现混淆。
您可以很好地使用上面的脚本化管道示例,但如果您想保留声明式管道,您可以 运行 script
步骤中的脚本部分。在这两种情况下,您都需要根据需要更改 docker 图像和执行的命令。
pipeline {
agent any
stages {
stage('Build and test') {
steps {
script {
node {
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'
}
}
}
}
}
}
}
}
请注意:
- Docker 容器 link 此示例中使用的功能是遗留功能,最终可能会被删除。
- 管道将在
make check
处失败,因为 centos:7
图像中未提供 make
。
半年多后,我终于发现它比我想象的要简单得多。可以用 docker-compose.
来完成
您需要确保您的 Jenkins 可以访问 docker-compose。因此,如果您将 运行 Jenkins 作为 docker 容器,请确保它可以访问 Docker 套接字。此外,Jenkins 不太可能附带 docker-compose (JENKINS-51898),因此您必须构建自己的蓝海映像才能安装 docker-compose。
与其复制以下文件,不如检查 https://docs.docker.com/compose/install/ 以获得最新版本!
# Dockerfile
FROM jenkinsci/blueocean
USER root
RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
USER jenkins
一旦你启动了 Jenkins 和 Docker 并且 运行 你可以使用常规 docker-compose 文件部署你的应用程序的测试版本,包括所有数据库和其他容器可能需要。您可以安装依赖项并通过使用 docker-compose exec
在以 docker-compose.
启动的容器内执行命令来启动测试
请注意,docker-compose -f docker-compose.test.yml exec -T php composer-install
在 docker-compose 文件中定义为 php
服务的容器中执行 composer-install
命令。
最后,无论测试结果如何,所有容器和相关卷(-v 标志)都将关闭并删除。
# Jenkinsfile
pipeline {
agent any
stages {
stage('Start') {
steps {
sh 'docker-compose -f docker-compose.test.yml up -d'
}
}
stage('Composer install') {
steps {
sh 'docker-compose -f docker-compose.test.yml exec -T php composer install --no-interaction --no-progress --optimize-autoloader'
}
}
stage('Test') {
steps {
sh 'docker-compose -f docker-compose.test.yml exec -T php <run test script>'
}
}
}
post {
always {
sh 'docker-compose -f docker-compose.test.yml down -v'
}
}
}
总的来说,我对 Jenkins 和 CI/CD 还很陌生,但相信我已经搜索了足够长的时间来得出结论,事情并不像我预期的那样。
我想在我的网站上做一些前端测试,就像在现实生活中一样,我想在一个 Docker 容器中测试网站,在另一个容器中测试数据库。 Jenkins 将此记录为 "sidecar" containers,它可以成为管道的一部分。
他们的例子:
node {
checkout scm
/*
* In order to communicate with the MySQL server, this Pipeline explicitly
* maps the port (`3306`) to a known port on the host machine.
*/
docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw" -p 3306:3306') { c ->
/* Wait until mysql service is up */
sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done'
/* Run some tests which require MySQL */
sh 'make check'
}
}
问题是我没有 'traditional' Jenkins 管道,但我是 运行 Jenkins Blue Ocean。这给了我一个漂亮的管道编辑器,但我的管道代码 (Jenkinsfile) 看起来与示例完全不同:
pipeline {
agent {
docker {
image 'php'
}
}
stages {
stage('Build') {
steps {
sh 'composer --version'
sh 'composer install'
}
}
stage('Tests') {
steps {
echo 'Do test'
}
}
}
}
那么我将如何在 Blue Ocean 管道中生成(和拆除)这些 "sidecar" 容器?如果我想添加与 Docker 相关的步骤,目前管道编辑器没有可用的选项。我还能使用 docker.image
吗?我确实安装了 Docker Pipeline plugin。
Jenkins在link中提供的示例实际上是一个功能齐全的管道,只有一个例外。如果您直接将管道脚本提供给 Jenkins,则需要注释掉 checkout scm
。
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'
}
}
}
可能让您感到困惑的是,上面示例中的代码风格与Blue Ocean pipeline editor 生成的代码风格有很大不同。那是因为脚本是写在Scripted Pipeline and Blue Ocean has generated a Declarative Pipeline的。两者都在 Jenkins 中得到完全支持,并且都在底层使用相同的引擎,但语法差异可能会导致开始时出现混淆。
您可以很好地使用上面的脚本化管道示例,但如果您想保留声明式管道,您可以 运行 script
步骤中的脚本部分。在这两种情况下,您都需要根据需要更改 docker 图像和执行的命令。
pipeline {
agent any
stages {
stage('Build and test') {
steps {
script {
node {
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'
}
}
}
}
}
}
}
}
请注意:
- Docker 容器 link 此示例中使用的功能是遗留功能,最终可能会被删除。
- 管道将在
make check
处失败,因为centos:7
图像中未提供make
。
半年多后,我终于发现它比我想象的要简单得多。可以用 docker-compose.
来完成您需要确保您的 Jenkins 可以访问 docker-compose。因此,如果您将 运行 Jenkins 作为 docker 容器,请确保它可以访问 Docker 套接字。此外,Jenkins 不太可能附带 docker-compose (JENKINS-51898),因此您必须构建自己的蓝海映像才能安装 docker-compose。
与其复制以下文件,不如检查 https://docs.docker.com/compose/install/ 以获得最新版本!
# Dockerfile
FROM jenkinsci/blueocean
USER root
RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
USER jenkins
一旦你启动了 Jenkins 和 Docker 并且 运行 你可以使用常规 docker-compose 文件部署你的应用程序的测试版本,包括所有数据库和其他容器可能需要。您可以安装依赖项并通过使用 docker-compose exec
在以 docker-compose.
请注意,docker-compose -f docker-compose.test.yml exec -T php composer-install
在 docker-compose 文件中定义为 php
服务的容器中执行 composer-install
命令。
最后,无论测试结果如何,所有容器和相关卷(-v 标志)都将关闭并删除。
# Jenkinsfile
pipeline {
agent any
stages {
stage('Start') {
steps {
sh 'docker-compose -f docker-compose.test.yml up -d'
}
}
stage('Composer install') {
steps {
sh 'docker-compose -f docker-compose.test.yml exec -T php composer install --no-interaction --no-progress --optimize-autoloader'
}
}
stage('Test') {
steps {
sh 'docker-compose -f docker-compose.test.yml exec -T php <run test script>'
}
}
}
post {
always {
sh 'docker-compose -f docker-compose.test.yml down -v'
}
}
}