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 conteneursmy_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:
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 variableWAIT_HOSTS
sont disponibles. La variable d’environnementWAIT_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:
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
- wait-for-it: Script bash pur pour tester et attendre la disponibilité d’un hôte et d’un port TCP](https://github.com/vishnubob/wait-for-it)
Version: English
No Comments