Forcer Docker Compose à Attendre que les Dépendances soient Prêtes

Forcer Docker Compose à Attendre que les Dépendances soient Prêtes

Forcer Docker Compose à Attendre que les Dépendances soient Prêtes

Cet article décrit comment configurer le fichier docker-compose.yml pour faire en sorte que docker compose attende que les dépendances soient prêtes avant de démarrer un conteneur d’application donné.

Nous allons introduire deux outils différents (dockerize et docker-compose-wait) pour faire en sorte que docker compose attende que le service ou les dépendances démarrent. Vous pouvez utiliser ces deux solutions pour déployer votre pile d’applications, en particulier lorsque vous souhaitez faire:

  • docker compose attendre mysql,
  • docker compose attendre postgres,
  • docker compose attendre redis ou
  • docker compose attendre mongodb

Vous apprendrez un exemple simple et complexe avec MongoDB, Postgres, MySQL.



Sommaire:

Exemple de fichier docker-compose.yml

L’exemple simple suivant comprend 2 services : my_super_app, qui dépend d’une base de données mysql.

version: '3.6'
services:
  mysql:
    image: "mysql:5.7"
    container_name: mysql
    restart: always
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=your_password
      - MYSQL_USER=root
      - MYSQL_PASSWORD=your_password
      - MYSQL_DATABASE=wordpress
    ports:
      - "3306:3306"

  my_super_app:
    build: ./my_super_app
    image: "my_super_app:latest"
    container_name: my_supper_app
    depends_on:
      - mysql

You can control the order of service startup and shutdown with the depends_on option. Compose démarre et arrête toujours les conteneurs dans l’ordre des dépendances, où les dépendances sont déterminées par depends_on, links, volumes_from, et network_mode: "service:...".

Cependant, au démarrage, Compose n’attend pas qu’un conteneur soit “prêt” (quoi que cela signifie pour votre application particulière) - seulement qu’il soit en cours d’exécution.

Le problème

Quand vous courez docker-compose up, docker starts the mysql database container first and then the my_super_app. Cependant, la base de données MySQL peut ne pas être prête avant l’exécution de l’application web.

L’application web va essayer de se connecter à la base de données, qui est peut-être encore en cours d’initialisation, ce qui entraîne le plantage de l’application. Et parce que c’est une course, vous ne verrez probablement pas ça à chaque fois.

La solution intermédiaire est d’ajouter restart : always à la configuration de notre application, pour réessayer jusqu’à ce que la base de données commence à répondre. Une meilleure solution consiste à utiliser l’un des outils suivants : outil dockerize, outil docker-compose-wait, wait-for et wait-for-it.

Solution 1 : Utilisation de l’outil dockerize

Description

Dockerize est un utilitaire pour simplifier l’exécution des applications dans les conteneurs docker. Il vous permet de:

  • générer des fichiers de configuration de l’application au démarrage du conteneur à partir de modèles et de variables d’environnement du conteneur
  • Afficher plusieurs fichiers logs vers stdout et/ou stderr
  • Attendez que d’autres services soient disponibles en utilisant TCP, HTTP(S), unix avant de lancer le processus principal.

Ici, nous allons nous concentrer sur comment faire en sorte que docker compose attende les autres dépendances. Dockerize vous donne la possibilité d’attendre des services sur un protocole spécifique (file, tcp, tcp4, tcp6, http, https et unix) avant de démarrer votre application:

dockerize -wait tcp://db:5432 -wait http://web:80 -wait file:///tmp/generated-file

Arguments importants:

  • timeout. You can optionally specify how long to wait for the services to become available by using the -timeout # argument (Default: 10 seconds). Si le délai d’attente est atteint et que le service n’est toujours pas disponible, le processus se termine avec le code de statut 1.
  • wait-retry-interval. Le temps de sommeil de dockerize avant de vérifier si les dépendances sont prêtes
dockerize -wait tcp://db:5432 -wait http://web:80 -timeout 10s -wait-retry-interval 3s

Démarrage rapide

# Download a template
git clone https://github.com/kassambara/docker-compose-wait-for-container.git

# Build the demo application
cd docker-compose-wait-for-container/ex02-using-dockerize-tool
docker-compose build
# Running your app
docker-compose run my_super_app

# Stopping containers and cleaning
docker-compose down 
rm -rf mysql

Etape 0 : Télécharger un modèle

# Download a template
git clone https://github.com/kassambara/docker-compose-wait-for-container.git
cd docker-compose-wait-for-container/ex02-using-dockerize-tool

Structure de dossier de projet:

files/docker-compose-wait-for-container/ex02-using-dockerize-tool
├── docker-compose.yml
└── my_super_app
    ├── Dockerfile
    └── sayhello

Contenu essentiel du projet:

  • docker-compose.yml pour gérer tous les services de conteneurs
  • my_super_app scripts : modèle Dockerfile pour construire votre application. Ici, cette application de démo vous demandera votre nom et vous félicitera ensuite !

Etape 1 : Ajouter dockerize au Dockerfile de votre application

Utilisez ceci pour l’image Ubuntu:

RUN apt-get update && apt-get install -y wget

ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz

Ou ceci pour les images alpines:

RUN apk add --no-cache openssl

ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz

Exemple de Dockerfile utilisant l’image alpine:

FROM alpine:latest

# Add hello scripts
ADD sayhello /sayhello
RUN chmod +x /sayhello

# Add dockerize tool -------------------
RUN apk add --no-cache openssl
ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz

CMD ["/sayhello"]

Etape 2 : Modifiez votre fichier docker-compose.yml

version: '3.6'
services:
  mysql:
    image: "mysql:5.7"
    container_name: mysql
    restart: always
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=your_password
      - MYSQL_USER=root
      - MYSQL_PASSWORD=your_password
      - MYSQL_DATABASE=wordpress
    ports:
      - "3306:3306"
    expose:
      - 3306

  my_super_app:
    build: ./my_super_app
    image: "my_super_app:latest"
    container_name: my_supper_app
    depends_on:
      - mysql
    command: sh -c "dockerize -wait tcp://mysql:3306 -timeout 300s -wait-retry-interval 30s /sayhello"

En gros, Dockerize est un emballage. dockerize notre_command_normal appelle juste notre commande. Mais en option, nous pouvons ajouter des paramètres pour retarder l’exécution, créer un template de fichier ou rediriger la sortie des fichiers vers STDOUT/STDERR. Opérations très courantes et utiles dans un monde de Docker.

Exemples de configurations optionnelles de dockerize:

# redirect files to stdout and stderr
dockerize \
  -stdout info.log \
  -stdout perf.log \
  ...

# wait for 2 services with 10s timeout
dockerize \
  -wait tcp://db:5432 \
  -wait http://web:80 \
  -timeout 10s \
  ...

# template option
dockerize \
  -template nginx.tmpl:nginx.conf \
  ...

Etape 3 : Créer et exécuter votre application

# Building your app
cd docker-compose-wait-for-container/ex02-using-dockerize-tool
docker-compose build
# Running your app
docker-compose run my_super_app

Plus de course ! Dockerize retarde le démarrage de notre commande jusqu’à ce que la base de données soit disponible. Pas seulement commencé - il attend des connexions. C’est une différence entre Dockerize et depends_on.

Log de la console:

Logs de l’attente de docker compose

Après avoir tapé votre nom, vous verrez un message de félicitations de my_super_app

Etape 4 : Arrêt des conteneurs et nettoyage

docker-compose down 
rm -rf mysql

Solution 2 : Utilisation de l’outil docker-composer-wait

Description

L’outil docker-compose-wait est un petit utilitaire en ligne de commande pour attendre que d’autres images docker soient lancées lors de l’utilisation de docker-compose. Il permet d’attendre un nombre fixe de secondes et/ou d’attendre qu’un port TCP soit ouvert sur une image cible.

Comme pour l’outil dockerize, vous devez ajouter l’outil docker-compose-wait dans votre application Dockerfile.



Démarrage rapide

# Download a template
git clone https://github.com/kassambara/docker-compose-wait-for-container.git

# Build the demo application
cd docker-compose-wait-for-container/ex01-using-wait-tool
docker-compose build
# Running your app
docker-compose run my_super_app

# Stopping containers and cleaning
docker-compose down 
rm -rf mysql

Etape 0 : Télécharger un modèle

# Download a template
git clone https://github.com/kassambara/docker-compose-wait-for-container.git
cd docker-compose-wait-for-container/ex02-using-dockerize-tool

Structure de dossier de projet:

files/docker-compose-wait-for-container/ex01-using-wait-tool
├── docker-compose.yml
└── my_super_app
    ├── Dockerfile
    └── sayhello

Etape 1 : Ajouter l’outil docker-compose-wait au Dockerfile de votre application

Exemple de Dockerfile utilisant l’image alpine:

FROM alpine:latest

# Add hello scripts
ADD sayhello /sayhello
RUN chmod +x /sayhello

# Add docker-compose-wait tool -------------------
ENV WAIT_VERSION 2.7.2
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/$WAIT_VERSION/wait /wait
RUN chmod +x /wait

CMD ["/sayhello"]

Etape 2 : Modifiez votre fichier docker-compose.yml

version: '3.6'
services:
  mysql:
    image: "mysql:5.7"
    container_name: mysql
    restart: always
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=your_password
      - MYSQL_USER=root
      - MYSQL_PASSWORD=your_password
      - MYSQL_DATABASE=wordpress
    ports:
      - "3306:3306"
    expose:
      - 3306

  my_super_app:
    build: ./my_super_app
    image: "my_super_app:latest"
    container_name: my_supper_app
    depends_on:
      - mysql
    command: sh -c "/wait && /sayhello"
    environment:
      - WAIT_HOSTS=mysql:3306
      - WAIT_HOSTS_TIMEOUT=300
      - WAIT_SLEEP_INTERVAL=30
      - WAIT_HOST_CONNECT_TIMEOUT=30
  • La commande sh -c “/wait && /sayhello” lancera l’outil wait et ensuite votre application, ici /sayhello.
  • Quand le docker-compose est lancé (ou Kubernetes ou docker stack ou autre), votre application sera lancée seulement quand toutes les paires host:port de la variable WAIT_HOSTS sont disponibles. Quand le docker-compose est lancé (ou Kubernetes ou docker stack ou autre), votre application sera lancée seulement quand toutes les paires host:port de la variable WAIT_HOSTS sont disponibles. La variable d’environnement WAIT_HOSTS n’est pas obligatoire, si elle n’est pas déclarée, le script s’exécute sans attendre.
  • Pour que votre conteneur d’application Docker attende plusieurs hôtes, la variable d’environnement peut être spécifiée comme ceci par exemple WAIT_HOSTS=mysql:3306, nginx:80

Options de configuration supplémentaires. Le comportement de l’utilitaire d’attente peut être configuré avec les variables d’environnement suivantes:

  • WAIT_HOSTS : liste séparée par des virgules des paires hôte:port pour lesquelles vous voulez attendre.
  • WAIT_HOSTS_TIMEOUT : nombre maximum de secondes d’attente pour que tous les hôtes soient disponibles avant l’échec. La valeur par défaut est de 30 secondes.
  • WAIT_HOST_CONNECT_TIMEOUT : Le délai d’attente d’une connexion TCP unique à un hôte distant avant de tenter une nouvelle connexion. La valeur par défaut est de 5 secondes.
  • WAIT_BEFORE_HOSTS : nombre de secondes à attendre (sleep) avant de commencer à vérifier la disponibilité des hôtes
  • WAIT_AFTER_HOSTS : nombre de secondes à attendre (sleep) une fois que tous les hôtes sont disponibles
  • WAIT_SLEEP_INTERVAL : nombre de secondes de sommeil entre deux tentatives. La valeur par défaut est 1 seconde.

Etape 3 : Créer et exécuter votre application

# Building your app
cd docker-compose-wait-for-container/ex01-using-wait-tool
docker-compose build
# Running your app
docker-compose run my_super_app

Log de la console:

Logs de l’attente de docker compose

Après avoir tapé votre nom, vous verrez un message de félicitations de my_super_app

Etape 4 : Arrêt des conteneurs et nettoyage

docker-compose down 
rm -rf mysql

Exemple complexe avec MongoDB, Postgres, MySQL

version: "3.6"

services:

  mongo:
    image: mongo:3.4
    hostname: mongo
    ports:
      - "27017:27017"

  postgres:
    image: "postgres:9.4"
    hostname: postgres
    ports:
      - "5432:5432"

  mysql:
    image: "mysql:5.7"
    hostname: mysql
    ports:
      - "3306:3306"

  my_super_app:
    build: ./my_super_app
    image: "my_super_app:latest"
    container_name: my_supper_app
    depends_on:
      - mysql
    command: sh -c "/wait && /sayhello"
    environment:
      - WAIT_HOSTS=postgres:5432, mysql:3306, mongo:27017
      - WAIT_HOSTS_TIMEOUT=300
      - WAIT_SLEEP_INTERVAL=30
      - WAIT_HOST_CONNECT_TIMEOUT=30

Résumé

Ce tutoriel décrit comment faire attendre les dépendances de conteneurs par les outils dockerize et docker-compose-wait.

Voir aussi



Version: English

Leçons

No Comments

Give a comment

Want to post an issue with R? If yes, please make sure you have read this: How to Include Reproducible R Script Examples in Datanovia Comments

Teachers