Cet article est la ** partie 5 ** des articles relatifs à ** Apprenez à utiliser Docker via la construction d'environnement Django + MySQL ** Cela correspond à.
Dans cet article, nous allons essayer de résoudre le problème de ** l'échec de connexion dû à l'ordre de démarrage ** qui peut se produire lors de l'exécution de plusieurs services dépendants à l'aide de docker-compose
.
Dans les articles jusqu'à Dernière fois, nous définissons la construction de l'environnement de Django
+ MySQL
en utilisant docker-compose.
Une fois les paramètres de base terminés, lorsque j'essaye de démarrer le serveur Django avec $ docker-compose up
,
** Même si le côté MySQL
n'est pas prêt, Django
essaie de se connecter à la DB
, et la situation ne progresse pas avec une erreur de connexion **. Cela peut finir.
Pour le moment, c'est un problème qui ne survient qu'au moment de l'exécution initiale, et si vous attendez la préparation du côté MySQL
, annulez-la manuellement une fois, et exécutez à nouveau $ docker-compose up
, la connexion réussira, mais dans le futur Afin d'éviter le même problème et le même désagrément lors de la modification du processus de travail, ** réfléchissez à la possibilité d'incorporer des contre-mesures à l'avance **.
Si la connexion avec la base de données échoue, l'erreur suivante sera envoyée et le conteneur côté Django deviendra rigide.
# (Extrait)
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)")
Cela semble être une erreur envoyée lors de la tentative de connexion à une base de données qui n'existe pas. En d'autres termes, dans ce cas, le problème est que la base de données n'est pas encore prête, alors réfléchissons à la possibilité d'ajuster l'ordre en attendant que cela puisse être fait par certains moyens.
Au fait, Docker recommande officiellement de résoudre avec le script shell, mais cette fois, le codage Python
et la connexion mysqlclient
Pour la pratique, je vais préparer un fichier Python
dédié et essayer de le résoudre **.
Les fichiers suivants sont préparés dans le répertoire config
.
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 #Ajustez la valeur au besoin
def check_connection(count, limit):
"""
docker-Compose up Fonction pour le réglage de l'heure à l'exécution
"""
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)
Ensuite, j'écrirai sur le contenu du code.
Tout d'abord, installez les bibliothèques et packages requis.
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
Pour local_settings.py
, déplacez le répertoire avec ʻos.chdir (Path (__ file__) .parent)` puis importez.
Ensuite, définissez les variables.
config/wait_for_db.py
count_to_try = 0
LIMIT_OF_COUNT = 20 #Ajustez la valeur au besoin
count_to_try
sert à compter le nombre de fois où la fonction décrite plus loin est appelée, et LIMIT_OF_COUNT
est la limite de nombre. Le branchement conditionnel est effectué dans la fonction de sorte que le fichier se termine après 20 répétitions. Ajustez cette valeur si nécessaire.
Pour le contenu de la fonction principale check_connection
,
try
,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,
)
L'instruction try
ʻunix_socket est la socket utilisée pour la connexion, mais elle est affichée dans le journal lorsque
$ docker-compose upest exécuté, vous pouvez donc le copier. Le reste est le même que celui de
Django` la dernière fois.
.
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.")
Pour l'instruction ʻexcept`, le nombre d'essais est compté et sorti, puis il attend 3 secondes, et quand il atteint 20 fois, le contenu de l'erreur est sorti et le fichier est terminé. La limite supérieure est définie pour empêcher une boucle infinie en cas d'erreur de connexion réelle. .
config/wait_for_db.py
else:
print("Connected!\n")
conn.close()
exit()
Lorsque la tentative de connexion réussit dans l'instruction try
(=> ** lorsque MySQL est prêt **), déclarez la connexion réussie dans l'instruction ʻelse`, fermez la connexion, puis quittez le fichier. ..
Si vous pouvez passer l'instruction ʻelse, la prochaine commande
runserver` devrait être exécutée sans délai.
.
config/wait_for_db.py
if __name__ == "__main__":
check_connection(count_to_try, LIMIT_OF_COUNT)
La dernière partie est ʻif name == "main": , c'est-à-dire **" lorsque ce fichier est exécuté directement "**, la fonction
check_connection` est lue. L'argument est la variable définie au début.
Enfin, ajoutez une description dans la commande
de docker-compose.yml
pour que ce fichier soit exécuté avant que le serveur ne s'exécute.
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
"
Vous avez maintenant un programme ** qui attend l'exécution de la commande ** runserver pour configurer MySQL.
Quand j'exécute réellement $ docker-compose up
...
# (Extrait)
djst_django | Waiting for MySQL... ( 1 / 20 )
# (Omission...)
djst_mysql | Version: '5.7.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
djst_django | Connected!
# (Omission...)
djst_django | Starting development server at http://0.0.0.0:8000/
djst_django | Quit the server with CONTROL-C.
Après avoir attendu, j'ai pu démarrer le serveur Django
en toute sécurité après avoir confirmé la connexion.
(Répétez de l'article précédent, en raison du réglage, le contrôle de fonctionnement réel n'est pas le http: //0.0.0.0: 8000 /
affiché, mais ** http://172.0.0.1 Cela se fera depuis: 8000 / ʻou
http: // localhost: 8000 / `**.)
Avec ce qui précède, l'objectif initial de ** l'ajustement du délai de démarrage du conteneur entre les services dépendants ** a été atteint. Si vous avez des suggestions, je vous serais reconnaissant de bien vouloir commenter.
Cette fois, je l'ai écrit en python pour l'entraînement, mais j'aimerais contester le script shell afin qu'il puisse être utilisé librement.
(Vous pouvez revenir à la première page à partir d'ici ↓.) Apprenez à utiliser Docker via la construction d'environnement Django + MySQL
Merci pour votre visite.
Recommended Posts