2015-04-10 13 views
45

Im Moment generieren unsere Jenkins-Agenten ein docker-compose.yml für jedes unserer Rails-Projekte und führen dann docker-compose up aus. Das docker-compose.yml hat einen Haupt "web" -Container, in dem rbenv und all unsere anderen Rails-Abhängigkeiten enthalten sind. Es ist mit einem DB-Container verbunden, der die Test-Postgres-DB enthält.Verwenden von docker-compose mit CI - Wie wird mit Exit-Codes und dämonisierten verknüpften Containern umgegangen?

Das Problem kommt, wenn wir die Tests tatsächlich ausführen und Exit-Codes generieren müssen. Unser CI-Server wird nur bereitgestellt, wenn das Testskript exit 0 zurückgibt, docker-compose jedoch immer 0 zurückgibt, auch wenn einer der Containerbefehle fehlschlägt.

Das andere Problem besteht darin, dass der DB-Container unbegrenzt ausgeführt wird, selbst nachdem der Webcontainer die Tests ausgeführt hat, sodass docker-compose up nie zurückkehrt.

Gibt es eine Möglichkeit, docker-compose für diesen Prozess zu verwenden? Wir müssten die Container ausführen können, aber nach Abschluss des Webcontainers beenden und den Exit-Code zurückgeben. Jetzt stecken wir fest, indem wir den Docker mit dem Andockfenster festmachen und den Web-Container mit der Option --link starten.

Antwort

25

docker-compose run ist die einfache Möglichkeit, die gewünschten Ausgangsstatus zu erhalten. Zum Beispiel:

$ 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 

Alternativ haben Sie die Möglichkeit, inspect die toten Behälter haben. Sie können das Flag -f verwenden, um nur den Exit-Status zu erhalten.

$ 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 

Was den db Container, der nie zurückgibt, wenn Sie docker-compose up verwenden, dann müssen Sie diesen Container SIGKILL; das ist wahrscheinlich nicht das was du willst. Stattdessen können Sie docker-compose up -d verwenden, um Ihre Daemon-Container auszuführen, und die Container manuell beenden, wenn der Test abgeschlossen ist. docker-compose runsollte verknüpfte Container für Sie ausführen, aber ich habe gehört Geschwätz über SO über einen Fehler verhindert, dass die Arbeit jetzt wie vorgesehen.

+0

Das Problem mit Docker Lauf ist, dass es keine Ausgabe geben, wenn sie mit -T laufen, und wir wollen, dass die Ausgabe so können wir baut inspect gescheitert. –

+0

@LoganSerman Sie können die Ausgabe mit 'docker-compose logs' überprüfen – kojiro

+0

Gibt es eine Möglichkeit, diese Protokolle während des Laufs konstant zu STDOUT zu leiten, damit wir es sehen können, während der CI-Build läuft? –

1

docker-rails können Sie angeben, welcher Fehlercode des Containers an den Hauptprozess zurückgegeben wird, damit der CI-Server das Ergebnis ermitteln kann. Es ist eine großartige Lösung für CI und Entwicklung für Schienen mit Docker.

Zum Beispiel

exit_code: web 

in Ihrem docker-rails.yml nachgeben den web Container Exit-Code als Folge des Befehls docker-rails ci test. docker-rails.yml ist nur ein Meta-Wrapper um den Standard docker-compose.yml, der Ihnen die Möglichkeit gibt, die gleiche Basiskonfiguration für verschiedene Umgebungen zu erben/wiederzuverwenden, d. H. Entwicklung vs Test vs Parallel_Tests.

18

Aufbauend auf kojiro Antwort:

docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d ' '

  1. get Container-IDs
  2. bekommen letzten Läufe Exit-Code für jeden Container ID
  3. nur Nicht-0-Statuscodes
  4. Zählnummer Nicht-0-Statuscodes
  5. Weißraum auskappen

Gibt zurück, wie viele Nicht-0-Exitcodes zurückgegeben wurden. Wäre 0 sein, wenn alles mit dem Code verläßt 0

+0

Sie können auch die nicht-stille Ausgabe von 'docker-compose ps' verwenden, zum Beispiel:' docker-compose ps | grep -c "Exit 1" 'gibt Ihnen die Anzahl, in der" Exit 1 "in der Anzeige von" docker-compose ps "abgeglichen wird (was eine hübsch gedruckte Übersichtstabelle der Ergebnisse liefert). Die Exit-Codes sind in der Spalte "State" aufgelistet. – eharik

4

Wenn Sie bereit sind docker-compose run zu verwenden manuell Ihre Tests zu beginnen, Hinzufügen der --rm Flagge, seltsam genug, verursacht Compose genau zu Ihrem Befehl des Exit-Status widerspiegelt.

Hier ist mein Beispiel:

$ 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. 
3

Verwenden docker wait den Exit-Code zu erhalten:

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

foo ist der "Projektname". Im obigen Beispiel habe ich es explizit angegeben, aber wenn Sie es nicht angeben, ist es der Verzeichnisname. bar ist der Name, den Sie dem zu testenden System in Ihrem docker-compose.yml geben.

Beachten Sie, dass docker logs -f auch das Richtige tut, wenn der Container stoppt. So können Sie

$ docker logs -f foo_bar_1 

zwischen dem docker-compose up setzen und die docker wait so können Sie Ihre Tests laufen zu sehen.

21

Seit der Version 1.12.0 können Sie die Option --exit-code-from verwenden.

Von documentation:

--exit-Code-von SERVICE

Rückkehr des Exit-Code der Service-Container ausgewählt. Impliziert --abort-on-container-exit.

+1

Das sollte der richtige Weg sein, wenn Sie '' 'docker-compose''' 1.12.0 und höher verwenden. Vielleicht ist es auch dein Fall. Ein Beispiel könnte sein: '' 'docker-compose up - exit-code-from-test-unit'''. Beachten Sie, dass es für mich nicht funktionierte, bis ich am Anfang meines Skripts ein '' 'set -e''' hinzugefügt habe. –

+0

'--exit-code-from' funktioniert jedoch nicht mit' -d'. Es wird diese Fehler werfen: 'using - exit-code-from impliziert --abort-on-container-exit' und' --abort-on-container-exit und -d kann nicht kombiniert werden. – ericat

+0

Ich konnte Bekommen Sie dieses Arbeiten auf Travis CI: https://Travis-ci.org/coyote-team/coyote/builds/274582053 hier ist die travis.yml: https://github.com/coyote-team/coyote/blob/ master/.travis.yml # L12 – subelsky

2

--exit-code-from SERVICE und --abort-on-container-exit nicht in Szenarien arbeiten, wo Sie alle Behälter vollständig ablaufen müssen, aber nicht, wenn einer von ihnen früh verlassen. Ein Beispiel könnte sein, wenn 2 Testanzüge gleichzeitig in verschiedenen Containern laufen.

Mit dem Vorschlag von @weedhil können Sie docker-compose in einem Skript umbrechen, das fehlschlägt, wenn Container dies tun.

#!/bin/bash 
set -e 

# Wrap docker-compose and return a non-zero exit code if any containers failed. 

docker-compose "[email protected]" 

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

Dann auf Ihrem CI einfach Server docker-compose up-./docker-compose.sh up ändern.

0

Sie sehen Status existieren kann mit:

echo $(docker-compose ps | grep "servicename" | awk '{print $4}') 
+0

Danke @Stephen Rauch für den richtigen Weg. –

Verwandte Themen