使用docker-comp和CI – 如何处理退出代码和守护进程链接的容器?
现在我们的Jenkins代理为我们的每个Rails项目生成一个docker-compose.yml,然后运行docker-compose。 docker-compose.yml有一个主要的“web”容器,里面有rbenv和所有其他的Rails依赖关系。 它链接到包含testingPostgres数据库的数据库容器。
当我们需要真正运行testing并生成退出代码时,问题就出现了。 如果testing脚本返回0出口,我们的CI服务器将只部署,但即使其中一个容器命令失败,docker-compose也总是返回0。
另一个问题是数据库容器无限期地运行,即使在web容器运行testing之后,所以docker-compose up
永远不会返回。
有没有一种方法可以使用docker-compose进行这个过程? 我们需要能够运行容器,但在web容器完成后退出并返回退出代码。 现在我们使用Docker手动停止,启动数据库容器并使用–link选项运行Web容器。
docker-compose run
是获取你想要的退出状态的简单方法。 例如:
$ cat docker-compose.yml roit: image: busybox command: 'true' naw: image: busybox command: 'false' $ docker-compose run --rm roit; echo $? Removing test_roit_run_1... 0 $ docker-compose run --rm naw; echo $? Removing test_naw_run_1... 1
或者,您可以select检查死容器。 您可以使用-f
标志来获取退出状态。
$ docker-compose up Creating test_naw_1... Creating test_roit_1... Attaching to test_roit_1 test_roit_1 exited with code 0 Gracefully stopping... (press Ctrl+C again to force) $ docker-compose ps -q | xargs docker inspect -f '{{ .Name }} exited with status {{ .State.ExitCode }}' /test_naw_1 exited with status 1 /test_roit_1 exited with status 0
至于从不返回的db容器,如果你使用docker docker-compose up
那么你将需要sigkill该容器; 这可能不是你想要的。 相反,您可以使用docker docker-compose up -d
运行您的容器,并在testing完成后手动终止容器。 docker-compose run
应该为你运行链接的容器,但是我听说过有关一个错误,防止从目前的工作。
以小二的回答为依据:
docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d ' '
- 获取容器ID
- 获取每个容器ID的最后一次运行退出代码
- 只有非0状态码
- 计数非0状态码的数量
- 修剪出白色的空间
返回有多less个非0退出码被返回。 如果所有内容都用代码0退出,则为0。
从版本1.12.0
,可以使用--exit-code-from
选项。
从文档 :
– 从SERVICE发出代码
返回所选服务容器的退出码。 意味着 – 在容器上退出。
如果您愿意使用docker-compose run
手动启动testing,添加--rm
标志足够奇怪,这会使Compose准确反映您的命令的退出状态。
这是我的例子:
$ docker-compose -v docker-compose version 1.7.0, build 0d7bf73 $ (docker-compose run kpi false) || echo 'Test failed!' # False negative. $ (docker-compose run --rm kpi false) || echo 'Test failed!' # True positive. Test failed! $ (docker-compose run --rm kpi true) || echo 'Test failed!' # True negative.
使用docker wait
获取退出代码:
$ docker-compose -p foo up -d $ ret=$(docker wait foo_bar_1)
foo
是“项目名称”。 在上面的例子中,我明确地指定了它,但是如果你不提供它,那就是目录名。 bar
是您在docker-compose.yml中给testing系统的名称。
请注意, docker logs -f
也是正确的,当容器停止时退出。 所以你可以放
$ docker logs -f foo_bar_1
在docker-compose up
之间docker-compose up
和docker wait
所以你可以看你的testing运行。
docker-rails允许你指定哪个容器的错误代码被返回到主进程,所以CI服务器可以确定结果。 这是一个伟大的CI解决scheme,并与docker的轨道发展。
例如
exit_code: web
在你docker-rails.yml
会产生web
容器的退出代码,作为命令docker-rails ci test
。 docker-rails.yml
只是一个标准docker-rails.yml
的meta wrapper,它可以为不同的环境(比如development vs test vs parallel_tests)inheritance/重用相同的基本configuration。
--exit-code-from SERVICE
和--abort-on-container-exit
在你需要运行所有容器完成的情况下不起作用,但是如果其中一个容器提前退出,则失败。 一个例子可能是如果在不同的容器中同时运行2个testing套装。
有了@ spenthil的build议,你可以将docker docker-compose
封装在脚本中,如果有容器的话,脚本将会失败。
#!/bin/bash set -e # Wrap docker-compose and return a non-zero exit code if any containers failed. docker-compose "$@" exit $(docker-compose -f docker-compose.ci.build.yml ps -q | tr -d '[:space:]' | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d '[:space:]')
然后,在您的CI服务器上,只需将./docker-compose.sh up
docker-compose up
更改为./docker-compose.sh up
。
你可以看到存在的状态:
echo $(docker-compose ps | grep "servicename" | awk '{print $4}')