J'essaie de m'assurer que mon conteneur d'applications n'exécute pas les migrations/démarrages tant que le conteneur de base de données n'est pas démarré et prêt à accepter les connexions.
J'ai donc décidé d'utiliser le bilan de santé et dépend de l'option dans docker compose le fichier v2.
Dans l'application, j'ai les éléments suivants
app:
...
depends_on:
db:
condition: service_healthy
Le db quant à lui a le bilan de santé suivant
db:
...
healthcheck:
test: TEST_GOES_HERE
timeout: 20s
retries: 10
J'ai essayé quelques approches comme:
test: ["CMD", "test -f var/lib/mysql/db"]
test: ["CMD", "echo 'SELECT version();'| mysql"]
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
Est-ce que quelqu'un a une solution à cela?
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
Le conteneur api ne démarrera pas tant que le conteneur de base de données ne sera pas en bon état (jusqu'à ce que mysqladmin soit opérationnel et accepte les connexions)
Si vous pouvez changer le conteneur pour attendre que mysql soit prêt, faites-le.
Si vous n'avez pas le contrôle du conteneur auquel vous souhaitez connecter la base de données, vous pouvez essayer d'attendre le port spécifique.
À cette fin, j'utilise un petit script pour attendre un port spécifique exposé par un autre conteneur.
Dans cet exemple, myserver attendra que le port 3306 du conteneur mydb soit accessible.
# 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
Vous pouvez trouver le script wait-for-it documentation ici
Si vous utilisez docker-compose v3 +, condition
en tant qu'option de depends_on
a été supprimé.
Le chemin recommandé est d'utiliser plutôt wait-for-it
, dockerize
ou wait-for
. Dans votre fichier docker-compose.yml
, modifiez votre commande pour qu'elle soit:
command: sh -c 'bin/wait-for db:3306 -- bundle exec Rails s'
Personnellement, je préfère wait-for
car il peut fonctionner dans un conteneur Alpine (compatible sh
, aucune dépendance de bash
). L'inconvénient est que cela dépend de netcat
. Par conséquent, si vous décidez de l'utiliser, assurez-vous que netcat
est installé dans le conteneur ou installez-le dans votre fichier Docker, par exemple avec:
RUN apt-get -q update && apt-get -qy install netcat
J'ai également lancé le wait-for
project afin qu'il puisse vérifier l'état HTTP en bon état (il utilise wget
). Ensuite, vous pouvez faire quelque chose comme ça:
command: sh -c 'bin/wait-for http://api/ping -- jest test'
Bonjour pour un bilan de santé simple en utilisant docker-compose v2.1 , j’ai utilisé:
/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\"
Fondamentalement, il exécute une simple commande mysql
SHOW DATABASES;
en utilisant à titre d'exemple l'utilisateur root
avec le mot de passe rootpasswd
dans la base de données.
Si la commande réussit, la base de données est active et prête à être vérifiée. Vous pouvez utiliser interval
pour qu'il teste à intervalles réguliers.
En retirant l’autre champ pour plus de visibilité, voici à quoi cela ressemblerait dans votre docker-compose.yaml
.
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
J'ai modifié le docker-compose.yml
selon l'exemple suivant et cela a fonctionné.
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
Dans mon cas, ../schemaAndSeedData
contient plusieurs fichiers SQL de schéma et de données. Design your own check script
peut être similaire à suivre select * from LastSchema.LastDBInsert
.
Alors que le code de conteneur dépendant du Web était
depends_on:
mysql:
condition: service_healthy
Cela devrait suffire
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