[GO] [Docker] Passen Sie den Startzeitpunkt des Containers zwischen abhängigen Diensten an. [Python]

Über diesen Artikel

Dieser Artikel ist ** Teil.5 ** von Artikeln im Zusammenhang mit ** Erfahren Sie, wie Sie Docker mithilfe der Django + MySQL-Umgebungskonstruktion verwenden ** Es entspricht.

  1. Erstellen einer virtuellen Python-Umgebung mit venv
  2. Beachten Sie die Beschreibung von Dockerfile
  3. Beachten Sie die Beschreibung von docker-compose.yml
  4. Bearbeiten Sie die Konfigurationsdatei und führen Sie Docker-Compose up aus
  5. ** Passen Sie den Startzeitpunkt des Containers zwischen abhängigen Diensten an (dieser Artikel) **

Einführung

In diesem Artikel werden wir versuchen, das Problem des ** Verbindungsfehlers aufgrund der Startreihenfolge ** zu lösen, das auftreten kann, wenn mehrere abhängige Dienste mit "Docker-Compose" ausgeführt werden.

In den Artikeln bis Letztes Mal legen wir die Umgebungskonstruktion von Django + MySQL mit Docker-Compose fest. Wenn ich versuche, den Django-Server mit "$ docker-compose up" zu starten, nachdem die Grundeinstellungen vorgenommen wurden, ** Obwohl die "MySQL" -Seite nicht bereit ist, versucht "Django", eine Verbindung zur "DB" herzustellen, und die Situation wird nicht mit einem Verbindungsfehler fortgesetzt **. Es kann enden.

Im Moment handelt es sich um ein Problem, das nur zum Zeitpunkt der Erstausführung auftritt. Wenn Sie auf der MySQL-Seite auf die Vorbereitung warten, diese einmal manuell abbrechen und "$ docker-compose up" erneut ausführen, ist die Verbindung erfolgreich, aber in Zukunft Um das gleiche Problem und den gleichen Ärger bei Änderungen im Arbeitsprozess zu vermeiden, ** überlegen Sie, ob Sie im Voraus Gegenmaßnahmen ergreifen können **.

Details des Fehlers

Wenn die Verbindung mit der Datenbank fehlschlägt, wird der folgende Fehler gesendet und der Container auf der Django-Seite wird starr.

# (Auszug)
djst_django | MySQLdb._exceptions.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")
djst_django | django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")

Es scheint ein Fehler zu sein, der gesendet wird, wenn versucht wird, eine Verbindung zu einer nicht vorhandenen Datenbank herzustellen. Mit anderen Worten, in diesem Fall besteht das Problem darin, dass die Datenbank noch nicht bereit ist. Überlegen wir uns also, ob wir die Reihenfolge anpassen können, indem wir warten, bis dies auf irgendeine Weise möglich ist.

Übrigens Docker empfiehlt offiziell das Lösen mit einem Shell-Skript, aber diesmal ist es die Codierung von "Python" und die Verbindung von "mysqlclient". Zum Üben werde ich eine dedizierte Python-Datei vorbereiten und versuchen, sie zu lösen **.

Dateiinhalt

Das ganze

Die folgenden Dateien werden im Verzeichnis config vorbereitet.

config/wait_for_db.py


import os
import MySQLdb
from time import sleep
from pathlib import Path

os.chdir(Path(__file__).parent)
from local_settings import DB_NAME, DB_USER, DB_PASSWORD


count_to_try = 0
LIMIT_OF_COUNT = 20 #Passen Sie den Wert nach Bedarf an


def check_connection(count, limit):
    """
    docker-Compose up Funktion zur Zeitanpassung zur Laufzeit.
    """
    try:
        conn = MySQLdb.connect(
            unix_socket = "/var/run/mysqld/mysqld.sock",
            user=DB_USER,
            passwd=DB_PASSWORD,
            host="db",
            port=3306,
            db=DB_NAME,
        )
    except MySQLdb._exceptions.OperationalError as e:
        count += 1
        print("Waiting for MySQL... (", count, "/ 20 )")
        sleep(3)
        if count < limit:
            check_connection(count, limit)
        else:
            print(e)
            print("Failed to connect mySQL.")
    else:
        print("Connected!\n")
        conn.close()
        exit()


if __name__ == "__main__":
    check_connection(count_to_try, LIMIT_OF_COUNT)

Über die Beschreibung

Als nächstes werde ich über den Inhalt des Codes schreiben.

Installieren Sie zunächst die erforderlichen Bibliotheken und Pakete.

config/wait_for_db.py


import os
import MySQLdb
from time import sleep
from pathlib import Path

os.chdir(Path(__file__).parent)
from local_settings import DB_NAME, DB_USER, DB_PASSWORD

Verschieben Sie für local_settings.py das Verzeichnis mit os.chdir (Pfad (__ file__) .parent) und importieren Sie es dann.

Definieren Sie als Nächstes die Variablen.

config/wait_for_db.py


count_to_try = 0
LIMIT_OF_COUNT = 20 #Passen Sie den Wert nach Bedarf an

count_to_try dient zum Zählen der Häufigkeit, mit der die später beschriebene Funktion aufgerufen wird, und LIMIT_OF_COUNT ist das Nummernlimit. In der Funktion wird eine bedingte Verzweigung durchgeführt, sodass die Datei nach 20-maliger Wiederholung beendet wird. Passen Sie diesen Wert nach Bedarf an.

Für den Inhalt der Hauptfunktion check_connection,

  1. Versuchen Sie, mit der Anweisung try eine Verbindung zu MySQL herzustellen.
  2. Wenn dies fehlschlägt, zählen Sie die Anzahl der Verbindungsversuche mit der Anweisung "Except" und wiederholen Sie die Funktion.
  3. Beenden Sie bei Erfolg die Verbindung mit der Anweisung "else" und schließen Sie diese Datei Es wird der Fluss sein.

config/wait_for_db.py


try:
    conn = MySQLdb.connect(
        unix_socket = "/var/run/mysqld/mysqld.sock",
        user=DB_USER,
        passwd=DB_PASSWORD,
        host="db",
        port=3306,
        db=DB_NAME,
    )

Das "unix_socket" der "try" -Anweisung ist der Socket, der für die Verbindung verwendet wird. Dies wird jedoch im Protokoll angezeigt, wenn "$ docker-compose up" ausgeführt wird, sodass Sie es kopieren können. Der Rest ist der gleiche wie der, der beim letzten Mal von Django gesetzt wurde. .

config/wait_for_db.py


except MySQLdb._exceptions.OperationalError as e:
    count += 1
    print("Waiting for MySQL... (", count, "/ 20 )")
    sleep(3)
    if count < limit:
        check_connection(count, limit)
    else:
        print(e)
        print("Failed to connect mySQL.")

Bei der Anweisung "Except" wird die Anzahl der Versuche gezählt und ausgegeben, dann 3 Sekunden gewartet, und wenn sie 20 Mal erreicht ist, wird der Fehlerinhalt ausgegeben und die Datei beendet. Die Obergrenze wird festgelegt, um eine Endlosschleife zu verhindern, wenn ein tatsächlicher Verbindungsfehler vorliegt. .

config/wait_for_db.py


else:
    print("Connected!\n")
    conn.close()
    exit()

Wenn die versuchte Verbindung in der Anweisung "try" erfolgreich ist (=> **, wenn MySQL bereit ist **), erklärt die Anweisung "else" die Verbindung für erfolgreich, schließt die Verbindung und beendet die Datei. ..

Wenn Sie die Anweisung "else" übergeben können, sollte der nächste Befehl "runserver" unverzüglich ausgeführt werden. .

config/wait_for_db.py


if __name__ == "__main__":
    check_connection(count_to_try, LIMIT_OF_COUNT)

Der letzte Teil ist if __name__ ==" __main__ ":, dh ** "wenn diese Datei direkt ausgeführt wird" **, wird die Funktion check_connection gelesen. Das Argument ist die am Anfang definierte Variable.

Fügen Sie abschließend eine Beschreibung in den Befehl von docker-compose.yml ein, damit diese Datei ausgeführt wird, bevor der Server ausgeführt wird.

docker-compose.yml


command: >
    bash -c "
        pip install -r requirements.txt &&
        python config/wait_for_db.py &&
        python manage.py runserver 0.0.0.0:8000
    "

Jetzt haben Sie ein Programm **, das auf die Ausführung des Befehls ** runserver wartet, um MySQL einzurichten.

Wenn ich tatsächlich "$ docker-compose up" ausführe ...

# (Auszug)
djst_django | Waiting for MySQL... ( 1 / 20 )
# (Unterlassung...)
djst_mysql | Version: '5.7.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
djst_django | Connected!
# (Unterlassung...)
djst_django | Starting development server at http://0.0.0.0:8000/
djst_django | Quit the server with CONTROL-C.

Nachdem ich gewartet hatte, konnte ich den Django-Server nach Bestätigung der Verbindung sicher starten. (Wiederholen Sie aus dem vorherigen Artikel, aufgrund der Einstellung ist die tatsächliche Funktionsprüfung nicht die angezeigte http: //0.0.0.0: 8000 /, sondern ** http://172.0.0.1 Dies erfolgt ab: 8000 / oder http: // localhost: 8000 / **.)

Am Ende

Mit dem oben Gesagten wurde der ursprüngliche Zweck der ** Anpassung des Container-Startzeitpunkts zwischen abhängigen Diensten ** erreicht. Wenn Sie Vorschläge haben, würde ich mich freuen, wenn Sie einen Kommentar abgeben könnten.

Dieses Mal habe ich es für das Training in Python geschrieben, aber ich möchte das Shell-Skript herausfordern, damit es frei verwendet werden kann.

(Sie können von hier aus zur ersten Seite zurückkehren ↓.) Erfahren Sie, wie Sie Docker mithilfe der Django + MySQL-Umgebungskonstruktion verwenden

Danke für Ihren Besuch.

Recommended Posts

[Docker] Passen Sie den Startzeitpunkt des Containers zwischen abhängigen Diensten an. [Python]
Passen Sie die Schriftunterschiede zwischen Qt für Python OS an
Fügen Sie Python3 in den Docker-Container von Amazon Linux2 ein
Verwenden Sie Python im Docker-Container als Pycharm-Interpreter
Probieren Sie den interaktiven Python-Modus in einem Docker-Container aus