Using docker-compose with CI - how to deal with ex

2019-01-21 05:06发布

Right now our Jenkins agents generate a docker-compose.yml for each of our Rails projects and then run docker-compose up. The docker-compose.yml has a main "web" container that has rbenv and all of our other Rails dependencies inside. It is linked to a DB container that contains the test Postgres DB.

The problem comes when we need to actually run the tests and generate exit codes. Our CI server will only deploy if the test script returns exit 0, but docker-compose always returns 0, even if one of the container commands fail.

The other issue is that the DB container runs indefinitely, even after the web container is done running the tests, so docker-compose up never returns.

Is there a way we can use docker-compose for this process? We would need to be able to run the containers, but exit after the web container is complete and return it's exit code. Right now we are stuck manually using docker to spin up the DB container and run the web container with the --link option.

9条回答
smile是对你的礼貌
2楼-- · 2019-01-21 06:02

In case you might run more docker-compose services with same name on one docker engine, and you don't know the exact name:

docker-compose up -d
(exit "${$(docker-compose logs -f test-chrome)##* }")

echo %? - returns exit code from test-chrome service

Benefits:

  • wait's for exact service to exit
  • uses service name, not container name
查看更多
女痞
3楼-- · 2019-01-21 06:06

Use docker wait to get the exit code:

$ docker-compose -p foo up -d
$ ret=$(docker wait foo_bar_1)

foo is the "project name". In the example above, I specified it explicitly, but if you don't supply it, it's the directory name. bar is the name you give to the system under test in your docker-compose.yml.

Note that docker logs -f does the right thing, too, exiting when the container stops. So you can put

$ docker logs -f foo_bar_1

between the docker-compose up and the docker wait so you can watch your tests run.

查看更多
冷血范
4楼-- · 2019-01-21 06:06

--exit-code-from SERVICE and --abort-on-container-exit don't work in scenarios where you need to run all containers to completion, but fail if one of them exited early. An example might be if running 2 test suits in concurrently in different containers.

With @spenthil's suggestion, you can wrap docker-compose in a script that will fail if any containers do.

#!/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:]')

Then on your CI server simply change docker-compose up to ./docker-compose.sh up.

查看更多
登录 后发表回答