Möglichkeiten zur Behebung des Problems 2003 (HY000): Verbindung zum MySQL-Server „db_mysql:3306' nicht möglich (111)
P粉178132828
P粉178132828 2023-09-05 11:18:47
0
1
831
<p>Ich habe kürzlich versucht, meinen FastAPI-Python-Server zu containerisieren (auch für Replikations-/Verdopplungszwecke). Vorher hatte ich nur einen MySQL-Server in einem Docker-Container und alles war in Ordnung, aber als ich meinen Webserver auch zu einem Dienst machte, konnte er keine Verbindung zum MySQL-Server herstellen, sodass die Anwendung jetzt nicht funktioniert.</p> <p>Das Folgende ist ein Codeausschnitt für den Server-Datenbank-Initialisierungs-Connector in der Anwendung</p> <pre class="lang-py Prettyprint-override"><code>aus Fastapi Import FastAPI mysql.connector importieren app = FastAPI() dbconfig = { "host": "localhost", "Datenbank": "server_db", "Benutzer": "db_user", "Passwort": "Benutzerpasswort" } # Datenbankverbindung prüfen versuchen: init_cnx = mysql.connector.connect( host='localhost', user='db_user', passwort='Benutzerpasswort' ) Cursor = init_cnx.cursor() Cursor.execute("DATENBANKEN WIE 'server_db' ANZEIGEN") if Cursor.fetchone() == None: # Wenn die Datenbank nicht vorhanden ist, erstellen Sie die Datenbank Cursor.execute("CREATE DATABASE server_db") Cursor.execute("USE server_db") Cursor.execute("CREATE TABLE-Nachrichten (" "message_id INT NOT NULL AUTO_INCREMENT," "Absendername VARCHAR(32)," "message_text VARCHAR(64)," "erstellt am DATUM" "user_messages_count INT," "PRIMÄRSCHLÜSSEL (message_id));") print('Datenbank wurde erstellt!') Cursor.close() init_cnx.close() außer mysql.connector.Error als Fehler: print("Ein Fehler ist in init_cnx aufgetreten:", err) # Datenbank-I/O-Funktion async defexecute_db_query(query,cursor_buffered=False): cnx = mysql.connector.connect(**dbconfig) versuchen: Cursor = cnx.cursor(buffered=cursor_buffered) Cursor.execute("USE server_db") Cursor.execute(Abfrage) Ergebnis = Cursor.fetchall() cnx.commit() print("Abfrage erfolgreich ausgeführt!") Ergebnis zurückgeben außer Ausnahme als e: print("Fehler beim Ausführen der Abfrage:", e) Endlich: wenn cnx: cnx.close() # Rufen Sie die Stammverzeichnisfunktion ab, mit der nur überprüft wird, ob die Anwendung mit der Datenbank verbunden ist @app.get("/") async def get_root(): versuchen: entries_count =waiteexecute_db_query("SELECT COUNT(*) FROM Messages", Cursor_buffered=True) return {"Nachrichteneinträge": Einträge_count[0][0]} außer Ausnahme als e: return {"Fehler": e} </code></pre> <p>Docker-Datei des Servers</p> <pre class="brush:php;toolbar:false;">FROM python:3.11.4-slim-bookworm WORKDIR/app KOPIEREN Sie „requirements.txt“. FÜHREN Sie pip install --no-cache-dir -r require.txt aus KOPIEREN Sie server.py . 8000 belichten CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]</pre> <p>init.sql-Skript</p> <pre class="lang-sql Prettyprint-override"><code>CREATE USER 'db_user'@'%' IDENTIFIED BY 'user-password'; GEWÄHREN SIE ALLE PRIVILEGIEN FÜR *.* TO 'db_user'@'%' WITH GRANT OPTION; FLUSH-PRIVILEGIEN; </code></pre> <p>und docker-compose.yml</p> <pre class="lang-yaml Prettyprint-override"><code>version: "3.8" Dienstleistungen: db_mysql: Bild: mysql:8 Neustart: immer Umfeld: MYSQL_ROOT_PASSWORD: "root" Bände: - "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql" - "./mysql/db_mysql_data:/var/lib/mysql" - "./mysql/mysql_logs:/var/log/mysql" Netzwerke: -dummy_network Server 1: Bild: dummy_msg_server Häfen: - „8081:8000“ Netzwerke: - dummy_network #Befehl: sh -c "sleep 60s" kommt drauf an: -db_mysql server_2: Bild: dummy_msg_server Häfen: - „8082:8000“ Netzwerke: - dummy_network #Befehl: sh -c "sleep 60s" kommt drauf an: -db_mysql Bände: db_mysql_data: #external: true Netzwerke: dummy_network: Fahrer: Brücke </code></pre> <p>Obwohl der Versuch, die API zu verwenden, bevor der MySQL-Container vollständig initialisiert wurde, zu einem Fehler führen kann, stellt dies kein Problem dar, da ich warte, bis der MySQL-Server anzeigt, dass er bereit ist, die Anfrage zu verarbeiten. Ansonsten versuche ich nicht, eine Verbindung zum MySQL-Server herzustellen. </p> <p>Ich habe versucht, eine Verbindung über den Hostnamen/die IP-Adresse herzustellen. Versuchen Sie, das python:3.11.4-Image in der Docker-Datei auf eine frühere Debian-Version zu ändern und nicht das Slim-Image zu verwenden.Versuchen Sie, explizit ein öffentliches Netzwerk für den Container zu verwenden. Docker zeigt ständig an, dass sich der Container in einem Netzwerk befindet, und die Curl-Anfrage vom Server-Container gibt etwas zurück. Darüber hinaus stellte docker-compose.yml zuvor Port 3306:3306 für den db_mysql-Dienst bereit. Ich schätze, das ist auch kein Problem. </p> <p><strong>Update 1. </strong>Während der Untersuchung wurde festgestellt, dass die Anwendung keine Probleme damit hat, Anfragen an sie zu senden und die richtige Antwort zu erhalten, wenn die Datenbank bereits erstellt wurde. Das einzige Problem dabei ist, dass die Datenbank nicht mit dem Erstellungsskript im Code erstellt werden kann. </p><p> (Ich schätze, ich sollte den Codeblock aktualisieren, da sich das Projekt jetzt in einer anderen Phase befindet.)</p>
P粉178132828
P粉178132828

Antworte allen(1)
P粉141455512

我遇到了一个问题,即服务器和数据库容器同时启动,导致出现问题。在数据库服务器准备好接受连接之前,第一次(也是最后一次)尝试连接数据库服务器就已经发生了。

为了解决这个问题,我决定在docker-compose.yml文件中添加一个健康检查:

version: "3.8"
services:
  db_mysql:
    image: mysql:8
    restart: always
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: "root"
    volumes:
      - "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql"
      - "./mysql/db_mysql_data:/var/lib/mysql"
      - "./mysql/mysql_logs:/var/log/mysql"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot"]
      timeout: 1s
      interval: 40s
      retries: 5

  server_1:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    ports:
      - "8081:8000"
    depends_on:
      db_mysql:
        condition: service_healthy

  server_2:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    ports:
      - "8082:8000"
    depends_on:
      db_mysql:
        condition: service_healthy

volumes:
  db_mysql_data: #external: true

使用这个配置,服务器的容器在健康检查确认数据库服务器准备好之前不会启动。

然而,有一种可能更好的处理这种情况的方法,涉及使用wait-for-it.sh脚本。我个人认识一些有经验的后端开发人员,他们也使用Docker容器将他们的应用程序拆分成微服务。他们对使用这个脚本表示了积极的评价。虽然我个人没有尝试过,但我建议考虑它作为一个替代解决方案。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage