W tej chwili nasi agenci Jenkinsa generują plik docker-compose.yml dla każdego z naszych projektów Rails, a następnie uruchamiają docker-compose. Docker-compose.yml ma główny kontener "sieciowy", który zawiera rbenv i wszystkie inne nasze zależności Railsowe. Jest powiązany z kontenerem DB, który zawiera testową bazę danych Postgres.
Problem pojawia się, gdy musimy faktycznie przeprowadzić testy i wygenerować kody wyjścia. Nasz serwer CI zostanie wdrożony tylko wtedy, gdy skrypt testowy zwróci exit 0, ale docker-compose zawsze zwraca 0, nawet jeśli jedno z poleceń kontenera zawiedzie.
Innym problemem jest to, że kontener bazy danych działa w nieskończoność, nawet po zakończeniu testów w kontenerze internetowym, więc docker-compose up
nigdy nie zwraca.
Czy istnieje sposób, w jaki możemy użyć docker-compose do tego procesu? Musielibyśmy mieć możliwość uruchomienia kontenerów, ale kończą pracę po zakończeniu kontenera internetowego i zwracają jego kod zakończenia. W tej chwili utknęliśmy ręcznie przy użyciu dockera, aby uruchomić kontener DB i uruchomić kontener sieciowy z opcją --link.
źródło
docker-compose
1.12.0 i nowszych. Może to też twoja sprawa. Przykładem mogą być:docker-compose up --exit-code-from test-unit
. Zauważ, że to nie zadziałało, dopóki nie dodałemset -e
na początku mojego skryptu.--exit-code-from
jednak nie działa-d
. Wyświetli te błędy:using --exit-code-from implies --abort-on-container-exit
i--abort-on-container-exit and -d cannot be combined.
docker-compose run
to prosty sposób na uzyskanie żądanych statusów zakończenia. Na przykład:Alternatywnie masz możliwość sprawdzenia martwych pojemników. Możesz użyć
-f
flagi, aby uzyskać tylko status wyjścia.Jeśli chodzi o kontener db, który nigdy nie powraca, jeśli używasz
docker-compose up
, będziesz musiał sigkill ten kontener; prawdopodobnie nie tego chcesz. Zamiast tego możesz użyćdocker-compose up -d
do uruchomienia kontenerów zdemonizowanych i ręcznie zabić kontenery po zakończeniu testu.docker-compose run
powinien uruchamiać połączone kontenery dla ciebie, ale słyszałem w SO gadkę o błędzie, który uniemożliwia to teraz działanie zgodnie z przeznaczeniem.źródło
docker-compose logs
-T
Opierając się na odpowiedzi Kojiro:
docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v '^0' | wc -l | tr -d ' '
Zwraca liczbę zwróconych kodów zakończenia innych niż 0. Byłoby 0, gdyby wszystko zakończyło się kodem 0.
źródło
docker-compose ps
, na przykład:docker-compose ps | grep -c "Exit 1"
da ci liczbę, do której dopasowano "Wyjście 1" na wyświetlaczu zdocker-compose ps
(co zapewnia ładnie wydrukowaną tabelę podsumowującą wyniki). Kody wyjścia są wymienione w kolumnie „Stan”.Jeśli chcesz
docker-compose run
ręcznie rozpocząć testy, dodanie--rm
flagi, co dziwne, powoduje, że komponowanie dokładnie odzwierciedla stan wyjścia polecenia.Oto mój przykład:
źródło
(docker-compose run --rm ...) || exit $?
do zakończenia w przypadku błędu. Przydatne w skryptach basha.Użyj,
docker wait
aby uzyskać kod wyjścia:foo
to „nazwa projektu”. W powyższym przykładzie wyraźnie to określiłem, ale jeśli go nie podasz, jest to nazwa katalogu.bar
to nazwa nadana testowanemu systemowi w pliku docker-compose.yml.Zauważ, że
docker logs -f
robi to również właściwą rzecz, wychodząc, gdy kontener się zatrzyma. Więc możesz umieścićmiędzy
docker-compose up
a dodocker wait
, abyś mógł oglądać przebieg testów.źródło
--exit-code-from SERVICE
i--abort-on-container-exit
nie działa w scenariuszach, w których trzeba uruchomić wszystkie kontenery do końca, ale kończy się niepowodzeniem, jeśli jeden z nich został wcześniej zakończony. Przykładem może być jednoczesne uruchomienie 2 zestawów testowych w różnych kontenerach.Dzięki sugestii @ Spedhil możesz zawrzeć
docker-compose
skrypt, który zawiedzie, jeśli zrobią to jakiekolwiek kontenery.Następnie na serwerze CI po prostu zmień
docker-compose up
na./docker-compose.sh up
.źródło
docker-rails pozwala określić, który kod błędu kontenera jest zwracany do procesu głównego, dzięki czemu serwer CI może określić wynik. Jest to świetne rozwiązanie dla CI i rozwoju dla szyn z dockerem.
Na przykład
w twoim
docker-rails.yml
zwróciweb
kod zakończenia kontenera w wyniku poleceniadocker-rails ci test
.docker-rails.yml
to tylko meta otoka wokół standardu,docker-compose.yml
która daje możliwość dziedziczenia / ponownego użycia tej samej podstawowej konfiguracji dla różnych środowisk, tj. programowanie vs test vs parallel_tests.źródło
W przypadku, gdy możesz uruchomić więcej usług docker-compose o tej samej nazwie na jednym silniku docker, a nie znasz dokładnej nazwy:
echo %?
- zwraca kod wyjścia z usługi test-chromeKorzyści:
źródło
Możesz zobaczyć status wyjścia za pomocą:
echo $(docker-compose ps | grep "servicename" | awk '{print $4}')
źródło
docker-compose ps | grep servicename | grep -v 'Exit 0' && echo "Automation or integration tests failed." && exit 1