使用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 ' '

  1. 获取容器ID
  2. 获取每个容器ID的最后一次运行退出代码
  3. 只有非0状态码
  4. 计数非0状态码的数量
  5. 修剪出白色的空间

返回有多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 updocker wait所以你可以看你的testing运行。

docker-rails允许你指定哪个容器的错误代码被返回到主进程,所以CI服务器可以确定结果。 这是一个伟大的CI解决scheme,并与docker的轨道发展。

例如

 exit_code: web 

在你docker-rails.yml会产生web容器的退出代码,作为命令docker-rails ci testdocker-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}')