在写测试代码时,我们会 mock 各种外部服务(比如测转账,显然不能真的调用银行转账接口),但不会 mock 基础设施,比如 MySQL、Redis、Elasticsearch。
而且跑测试用的 MySQL 等服务都是一次性的,跑完就清空数据不再需要了,所以买台服务器长期开着是不划算的。最佳实践是:测试时启动多个 Docker 后台服务。
在 CircleCI 中,启动多个 Docker image 很方便,但不支持 Dockerfile,导致 Dockerfile 和 config.yml 重复,违反 DRY。
在 Jenkins 中也可以实现,而且更强大(支持 Dockerfile)。
查看 Jenkins 官方文档,发现 sidecar 只支持2个 Docker,无法支持3个(比如 MySQL、Redis 作为服务,debian 跑 tests);而且用了 link,已被 Docker 官方淘汰:
Warning: The --link flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link.
按照 Docker 官方推荐,创建一个网络即可。关键在于等待启动成功,代码如下(完整代码):
node {
checkout scm
sh 'docker network create bridge1';
sh(script:'docker run --net bridge1 --name mysql -d -e "MYSQL_ROOT_PASSWORD=my-secret-pw" -e "MYSQL_DATABASE=test" mysql:5.7', returnStdout: true)
sh(script:'docker run --net bridge1 --name redis -d redis:5', returnStdout: true)
def testImage = docker.build("test-image:${env.BUILD_ID}", "-f Dockerfile ./")
testImage.inside('--net bridge1 -e "DB_HOST=mysql" -e "REDIS_HOST=redis" -e "DB_DATABASE=test" -e "DB_USERNAME=root" -e "DB_PASSWORD=my-secret-pw"') {
stage('prepare') {
echo 'preparing'
sh 'apt-get update && apt-get install -y librsvg2-bin'
}
stage('test') {
echo 'testing...'
sh './unit.sh'
}
}
}
已在 coding.net 持续集成(免费的 Jenkins 云服务)中运行成功,截图: