2017-02-13 13 views
6

Jaki byłby najlepszy sposób oczekiwania na postgres, aby w pełni rozpocząć pracę z moim ENTRYPOINT przed przejściem do wykonywania nosetests?Jak czekać na uruchomienie PostgreSQL w ENTRYPOINT?

W tej chwili mam czas rozruchu na moim komputerze do około 50 sekund. Więc śpię tylko przez 60 sekund. To nie jest dobre, ponieważ może nie działać, gdy jest uruchamiany na innej maszynie.

ENTRYPOINT \ 
      runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf & ' && \ 
      sleep 60 && \ 
      nosetests --verbose --cover-erase --with-coverage --cover-package=stalker 

Jest to wyjście z uruchomieniem postgres:

2017-02-13 13:46:49.541 UTC [9] LOG: database system was interrupted; last known up at 2017-02-13 12:53:23 UTC 
2017-02-13 13:47:37.951 UTC [9] LOG: database system was not properly shut down; automatic recovery in progress 
2017-02-13 13:47:37.994 UTC [9] LOG: redo starts at 0/1783EA0 
2017-02-13 13:47:37.995 UTC [9] LOG: record with zero length at 0/17841E8 
2017-02-13 13:47:37.995 UTC [9] LOG: redo done at 0/17841B8 
2017-02-13 13:47:37.995 UTC [9] LOG: last completed transaction was at log time 2017-02-13 12:53:23.731984+00 
2017-02-13 13:47:38.384 UTC [9] LOG: MultiXact member wraparound protections are now enabled 
2017-02-13 13:47:38.387 UTC [7] LOG: database system is ready to accept connections 
2017-02-13 13:47:38.387 UTC [13] LOG: autovacuum launcher started 

Proszę, ja rozumiem, że to jest sprzeczne z konwencją prowadzenia wielu poleceń w ENTRYPOINT. Mam dobre powody, aby to zrobić w tym przypadku.

+1

można uruchomić [ 'pg_isready'] (https://www.postgresql.org/docs/current /static/app-pg-isready.html) w pętli, podczas gdy kod powrotu to 1. –

Odpowiedz

0

Zawsze lepiej nie uruchamiać wielu rzeczy w jednym pojemniku. Najlepszym sposobem byłoby, abyś miał postgres działać w jednym kontenerze, a inny dla swojego nosetests.

Można utworzyć plik dokowanego pliku, w którym nosetest "zależy" od bazy danych.

+0

_depends_ wymusza tylko kolejność uruchamiania kontenerów, ale fakt, że kontener postgresowy został uruchomiony, nie oznacza, że ​​jest gotowy aby zaakceptować połączenia (tzn. gotowe do testu), więc musisz również użyć poprawnego [healthcheck] (https://docs.docker.com/compose/compose-file/#/healthcheck), aby sprawdzić, że proces _postgress_ wewnątrz zawieść r jest naprawdę gotowy. – zeppelin

+0

To naprawdę dobry punkt i nie mam pojęcia, jak to odpuścić. Również podczas gdy stoję w 100% za moim argumentem, nie jest to pełna odpowiedź, ponieważ tak naprawdę nie rozwiązuje problemu. – Nanne

1

będę normalnie użyć małego "tcp-port-Wait" skrypt tak:

#!/bin/bash 
set -e 

if [ -z "$1" -o -z "$2" ] 
then 
    echo "tcp-port-wait - block until specified TCP port becomes available" 
    echo "Usage: ntcp-port-wait HOST PORT" 
    exit 1 
fi 
echo Waiting for port $1:$2 to become available... 
while ! nc -z $1 $2 2>/dev/null 
do 
    let elapsed=elapsed+1 
    if [ "$elapsed" -gt 90 ] 
    then 
     echo "TIMED OUT !" 
     exit 1 
    fi 
    sleep 1; 
done 

echo "READY !" 

poczekać, aż pewna usługa jest i gotowe.

W przypadku PostgreSQL, domyślnym portem będzie nasłuchiwać jest , więc polecenie będzie:

tcp-port-wait localhost 5432 

To będzie blokować aż usługi PostgreSQL jest gotowa służyć połączeń na: 5432 na interfejs pętli zwrotnej wewnątrz kontenera (gdy uruchamiany jest w kontekście skryptu ENTRYPOINT).

pewno trzeba skopiować ten skrypt do swojego pojemnika, przez dodanie odpowiedniego wiersza podobnego do Dockerfile:

COPY tcp-port-wait /usr/local/bin/ 

, zanim będzie można go używać.

A także zainstalować narzędzie netcat.

Można tego użyć do innych rodzajów usług, takich jak Tomcat lub MySQL.

A jeśli trzeba, można też czekać „na zewnątrz pojemnika”, tak:

docker exec my_container tcp-port-wait localhost 5432 

Uwaga, istnieje oczywiście inne sposoby, aby to zrobić, na przykład za pomocą narzędzia orkiestracji, takiego jak dokowanie-komponowanie z healthcheck directive lub jakiegoś menedżera procesów wewnątrz samego kontenera.

+0

To wygląda świetnie, ale dla mnie ten skrypt od razu myśli, że db jest w górze: http://pastebin.com/x8UwhHQD – fredrik

+0

Hmm, to dziwne, najwyraźniej akceptuje połączenia, gdy trwa odzyskiwanie, spróbuj zastąpić 'nc - z $ 1 $ 2' z 'pg_isready' (który jest narzędziem specyficznym dla PostgreSQL w celu sprawdzenia jego statusu) i sprawdź, czy to pomaga. – zeppelin

+0

Dzięki, działało 'pg_isready'! Musiałem też usunąć sprawdzanie argumentów. Jeśli chcesz zmodyfikować swoją odpowiedź, oznaczę ją jako zaakceptowaną. – fredrik

7

Dzięki @Zeppelin za sugerowanie pg_isready.I skończyło się tak:

#!/bin/bash 
# wait-for-postgres.sh 

set -e 

cmd="[email protected]" 
timer="5" 

until runuser -l postgres -c 'pg_isready' 2>/dev/null; do 
    >&2 echo "Postgres is unavailable - sleeping for $timer seconds" 
    sleep $timer 
done 

>&2 echo "Postgres is up - executing command" 
exec $cmd 

Używam tego w moim ENTRYPOINT:

ENTRYPOINT \ 

      # Start PostgreSQL 
      runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf & ' && \ 

      # Exectute tests when db is up 
      ./wait-for-postgres.sh nosetests --verbose --cover-erase --with-coverage --cover-package=stalker 
Powiązane problemy