Méthodes de résolution du problème 2003 (HY000) : Impossible de se connecter au serveur MySQL 'db_mysql:3306' (111)
<p>J'ai récemment essayé de conteneuriser mon serveur FastAPI Python (également à des fins de réplication/doublement). Avant, je n'avais qu'un serveur MySQL dans un conteneur Docker et tout allait bien, mais lorsque j'ai également fait de mon serveur Web un service, il ne pouvait pas se connecter au serveur MySQL, donc maintenant l'application ne fonctionne plus.</p>
<p>Ce qui suit est un extrait de code pour le connecteur d'initialisation de la base de données du serveur dans l'application</p>
<pre class="lang-py Prettyprint-override"><code>à partir de l'importation fastapi FastAPI
importer mysql.connector
application = FastAPI()
dbconfig = {
"hôte": "localhost",
"base de données": "server_db",
"utilisateur": "db_user",
"mot de passe": "mot de passe utilisateur"
}
# Vérifier la connexion à la base de données
essayer:
init_cnx = mysql.connector.connect(
hôte='localhost',
utilisateur='db_user',
mot de passe='mot de passe utilisateur'
)
curseur = init_cnx.cursor()
curseur.execute("AFFICHER LES BASES DE DONNÉES COMME 'server_db'")
si curseur.fetchone() == Aucun :
# Si la base de données n'existe pas, créez la base de données
curseur.execute("CREATE DATABASE server_db")
curseur.execute("USE server_db")
curseur.execute("CREATE TABLE Messages (""
"message_id INT NON NULL AUTO_INCREMENT","
"nom_expéditeur VARCHAR(32)"
"message_text VARCHAR(64)"
"créé_au DATE",
"user_messages_count INT",
"CLÉ PRIMAIRE (message_id));")
print('La base de données a été créée !')
curseur.close()
init_cnx.close()
sauf mysql.connector.Error comme erreur :
print("Une erreur s'est produite dans init_cnx:", euh)
# Fonction d'E/S de base de données
async def execute_db_query(query, curseur_buffered=False) :
cnx = mysql.connector.connect(**dbconfig)
essayer:
curseur = cnx.cursor(buffered=cursor_buffered)
curseur.execute("USE server_db")
curseur.execute (requête)
résultat = curseur.fetchall()
cnx.commit()
print("Requête exécutée avec succès !")
résultat de retour
sauf exception comme e :
print("Erreur lors de l'exécution de la requête :", e)
enfin:
si cnx :
cnx.close()
# Récupère la fonction du répertoire racine, juste utilisée pour vérifier si l'application est connectée à la base de données
@app.get("/")
async def get_root() :
essayer:
entrées_count = attendre exécuter_db_query("SELECT COUNT(*) FROM Messages", curseur_buffered=True)
return {"Entrées de messages" : entrées_count[0][0]}
sauf exception comme e :
return {"Erreur": e}
</code></pre>
<p> Dockerfile du serveur</p>
<pre class="brush:php;toolbar:false;">DEpuis python:3.11.4-slim-bookworm
TRAVAIL/application
COPIER exigences.txt .
EXÉCUTER pip install --no-cache-dir -r conditions.txt
COPIER serveur.py .
EXPOSER 8000
CMD ["uvicorn", "serveur: application", "--hôte", "0.0.0.0", "--port", "8000"]</pre>
<p>script init.sql</p>
<pre class="lang-sql Prettyprint-override"><code>CREATE USER 'db_user'@'%' IDENTIFIÉ PAR 'user-password';
ACCORDEZ TOUS LES PRIVILÈGES SUR *.* À 'db_user'@'%' AVEC OPTION D'OBTENTION ;
PRIVILÈGES FLUSH ;
</code></pre>
<p>et docker-compose.yml</p>
<pre class="lang-yaml Prettyprint-override"><code>version : "3.8"
prestations de service:
db_mysql :
image : mysql:8
redémarrer : toujours
environnement:
MYSQL_ROOT_PASSWORD : "racine"
tomes :
- "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql"
- "./mysql/db_mysql_data:/var/lib/mysql"
- "./mysql/mysql_logs:/var/log/mysql"
réseaux :
- réseau_fictif
serveur_1 :
image : dummy_msg_server
ports :
- "8081:8000"
réseaux :
- réseau_fictif
#commande : sh -c "dormir 60 s"
dépend de:
-db_mysql
serveur_2 :
image : dummy_msg_server
ports :
- "8082:8000"
réseaux :
- réseau_fictif
#commande : sh -c "dormir 60 s"
dépend de:
-db_mysql
tomes :
db_mysql_data : #external : vrai
réseaux :
réseau_fictif :
pilote : pont
</code></pre>
<p>Bien que tenter d'utiliser l'API avant que le conteneur MySQL ne soit complètement initialisé puisse entraîner une erreur, ce n'est pas un problème car j'attends que le serveur MySQL indique qu'il est prêt à traiter la requête. A part ça, je n'essaye pas de me connecter au serveur MySQL. </p>
<p>J'ai essayé de me connecter en utilisant le nom d'hôte/l'adresse IP.
Essayez de remplacer l'image python:3.11.4 dans le fichier docker par une version Debian antérieure et de ne pas utiliser l'image slim.Essayez d'utiliser explicitement un réseau public pour le conteneur. Docker continue d'afficher que le conteneur est dans un réseau et la requête curl du conteneur du serveur renvoie quelque chose.
De plus, docker-compose.yml fournissait précédemment le port 3306:3306 pour le service db_mysql. Je suppose que ce n'est pas un problème non plus. </p>
<p><strong>Mise à jour 1. </strong>Au cours de l'enquête, il a été découvert que si la base de données a déjà été créée, l'application n'a aucun problème à lui envoyer des requêtes et à obtenir la réponse correcte. Le seul problème est que la base de données ne peut pas être créée à l’aide du script de création dans le code. </p><p>
(Je suppose que je devrais mettre à jour le bloc de code puisque le projet est maintenant dans une autre phase.)</p>