web-dev-qa-db-fra.com

Docker-compose vérifie si la connexion mysql est prête

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:

  1. en vous assurant que le répertoire de base de données est créé test: ["CMD", "test -f var/lib/mysql/db"]
  2. Obtenir la version de MySQL: test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. Envoyez une requête ping à l’administrateur (marque le conteneur de base de données comme sain mais ne semble pas être un test valide) test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]

Est-ce que quelqu'un a une solution à cela?

40
John Kariuki
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)

49
John Kariuki

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

6
nono

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'
3
Capripot

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 mysqlSHOW 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
2
Sylhare

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
2
Mukesh Agarwal

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
0
Maksim Kostromin