wake-up-neo.com

Docker-Compose-Prüfung, ob die MySQL-Verbindung bereit ist

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:

  1. stellen Sie sicher, dass das Datenbank-DIR erstellt wird test: ["CMD", "test -f var/lib/mysql/db"]
  2. Abrufen der MySQL-Version: test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. Pingen Sie den Administrator an (markiert den Datenbankcontainer als fehlerfrei, scheint jedoch kein gültiger Test zu sein) test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]

Hat jemand eine Lösung dafür?

40
John Kariuki
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.)

49
John Kariuki

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

6
nono

Wenn Sie Docker-Compose v3 + verwenden, wurde condition als Option von depends_onentfernt.

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'
3
Capripot

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
2
Sylhare

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
2
Mukesh Agarwal

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
0