Ich versuche sicherzustellen, dass mein App-Container keine Migrationen/Starts ausführt, bis der db-Container gestartet ist und BEREIT zum Akzeptieren von Verbindungen ist.
Also entschied ich mich für den Healthcheck und hängt von der Option in der Docker-Compose-Datei v2 ab.
In der App habe ich Folgendes
app:
...
depends_on:
db:
condition: service_healthy
Die Datenbank hat dagegen den folgenden Gesundheitscheck
db:
...
healthcheck:
test: TEST_GOES_HERE
timeout: 20s
retries: 10
Ich habe ein paar Ansätze ausprobiert:
test: ["CMD", "test -f var/lib/mysql/db"]
test: ["CMD", "echo 'SELECT version();'| mysql"]
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
Hat jemand eine Lösung dafür?
version: "2.1"
services:
api:
build: .
container_name: api
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
db:
container_name: db
image: mysql
ports:
- "3306"
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_USER: "user"
MYSQL_PASSWORD: "password"
MYSQL_DATABASE: "database"
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
timeout: 20s
retries: 10
Der API-Container wird erst gestartet, wenn der Datenbankcontainer fehlerfrei ist (im Wesentlichen bis mysqladmin aktiv ist und Verbindungen akzeptiert.)
Wenn Sie den Container ändern können, um zu warten, bis mysql fertig ist, tun Sie es.
Wenn Sie nicht die Kontrolle über den Container haben, mit dem Sie die Datenbank verbinden möchten, können Sie versuchen, auf den bestimmten Port zu warten.
Zu diesem Zweck verwende ich ein kleines Skript, um auf einen bestimmten Port zu warten, der von einem anderen Container verfügbar gemacht wird.
In diesem Beispiel wartet myserver, bis der Port 3306 des mydb -Containers erreichbar ist.
# Your database
mydb:
image: mysql
ports:
- "3306:3306"
volumes:
- yourDataDir:/var/lib/mysql
# Your server
myserver:
image: myserver
ports:
- "....:...."
entrypoint: ./wait-for-it.sh mydb:3306 -- ./yourEntryPoint.sh
Sie finden das Skript wait-for-it Dokumentation hier
Wenn Sie Docker-Compose v3 + verwenden, wurde condition
als Option von depends_on
entfernt.
Der empfohlene Pfad ist die Verwendung von wait-for-it
, dockerize
oder wait-for
. Ändern Sie in Ihrer docker-compose.yml
-Datei Ihren Befehl in:
command: sh -c 'bin/wait-for db:3306 -- bundle exec Rails s'
Ich persönlich bevorzuge wait-for
, da er in einem Alpine-Container ausgeführt werden kann (sh
-kompatibel, keine Abhängigkeit von bash
). Der Nachteil ist, dass es von netcat
abhängt. Wenn Sie sich also entscheiden, es zu verwenden, vergewissern Sie sich, dass Sie netcat
im Container installiert haben, oder installieren Sie es in Ihrer Dockerfile.
RUN apt-get -q update && apt-get -qy install netcat
Ich habe auch verzweigte das wait-for
Projekt, damit es den HTTP-Status überprüfen kann (es verwendet wget
). Dann kannst du so etwas machen:
command: sh -c 'bin/wait-for http://api/ping -- jest test'
Hallo für einen einfachen Healthcheck mit docker-compose v2.1 , habe ich verwendet:
/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\"
Grundsätzlich wird ein einfacher mysql
-Befehl SHOW DATABASES;
ausgeführt, der als Beispiel den Benutzer root
mit dem Kennwort rootpasswd
in der Datenbank verwendet.
Wenn der Befehl erfolgreich ist, ist die Datenbank bereit und der Healthcheck-Pfad ist also bereit. Sie können interval
verwenden, damit es im Intervall getestet wird.
Entfernen Sie das andere Feld für die Sichtbarkeit, so würde es in Ihrem docker-compose.yaml
aussehen.
version: '2.1'
services:
db:
...
healthcheck:
test: "/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\""
interval: 2s
timeout: 20s
retries: 10
app:
...
depends_on:
db:
condition: service_healthy
Ich änderte den docker-compose.yml
wie im folgenden Beispiel und es hat funktioniert.
mysql:
image: mysql:5.6
ports:
- "3306:3306"
volumes:
# Preload files for data
- ../schemaAndSeedData:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: rootPass
MYSQL_DATABASE: DefaultDB
MYSQL_USER: usr
MYSQL_PASSWORD: usr
healthcheck:
test: mysql --user=root --password=rootPass -e 'Design your own check script ' LastSchema
In meinem Fall enthält ../schemaAndSeedData
mehrere Schema- und Datenseeding-SQL-Dateien. Design your own check script
kann dem folgenden select * from LastSchema.LastDBInsert
ähneln.
Während webabhängiger Containercode war
depends_on:
mysql:
condition: service_healthy
Das sollte reichen
version: '2.1'
services:
mysql:
image: mysql
ports: ['3306:3306']
environment:
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD