Utilisation de Docker Compose
Introduction
Préparation
Comme pour la construction d'image, Docker compose a besoin d'un répertoire, d'un fichier de configuration (compose.yaml) et de ressources afin de déployer une application. Attention : dans un fichier YAML, l'indentation (assurée par deux espaces) marque les relations père-fils entre les paramètres.
## Créer un répertoire et le choisir mkdir movies-app cd movies-app ## Créer le fichier compose.yaml cat > compose.yaml <<FIN name: movies-app # Cette application sera composée de trois parties include: - database.yaml - web.yaml - front.yaml # La partie réseau pour connecter les parties networks: mynet: driver: bridge FIN ## Les trois parties sont vides cat /dev/null > database.yaml cat /dev/null > web.yaml cat /dev/null > front.yaml
Nous allons utiliser les commandes docker compose build pour construire (mais il n'y a rien à construire), docker compose ps pour lister (mais rien à lister) et docker compose rm pour supprimer (idem).
## Construire les images docker compose build ## Lister les services docker compose ps ## Stopper les services docker compose rm --stop --force
La partie données
Nous allons ajouter une base de données à notre application. Nous retrouvons les paramètres que nous utilisions sur la ligne de commande dans les exercices précédents.
## Créer un répertoire pour la DB mkdir -p /var/movies/db ## Créer le fichier database.yaml cat > database.yaml <<FIN services: ## Définition des services ## La partie données database: image: mysql ## Toujours redémarrer restart: always ## Les paramètres de ma BD environment: MYSQL_ROOT_PASSWORD: rootpasswd MYSQL_USER: moviesuser MYSQL_PASSWORD: moviespass MYSQL_DATABASE: moviesdb ## Pour pérenniser les données dans /var/movies/db volumes: - /var/movies/db:/var/lib/mysql ## Pour communiquer avec les autres conteneurs ## qui sont dans le même réseau. networks: - mynet ## Pour tester l'état de ma BD healthcheck: test: /usr/bin/mysql --user=root --password=rootpasswd \ --execute "SHOW DATABASES;" interval: 2s timeout: 20s retries: 100 FIN
Utilisons maintenant docker compose up pour démarrer notre application.
## Lancer les services et attendre le statut healthy docker compose up -d --wait --build ## Lister les services docker compose ps ## Attendre les services - normalement inutile wait-for-healthy-container movies-app-database-1 600 ## Stopper les services docker compose rm --stop --force
La partie WEB
Continuons avec la partie WEB (deux instances de notre application Spring-Boot) :
## À faire dans le répertoire movies-app/ mkdir web ## Préparer le WAR dans le répertoire wget http://tinyurl.com/jlmassat2/cca/spring-app.war -O web/spring-app.war ## Créer le script de démarrage cat > web/start.sh <<FIN exec &> \$MYAPP_LOG-\$(uname -n) echo "DB_URL is \$MYAPP_DB_URL" echo "DB_DRIVER is \$MYAPP_DB_DRIVER" echo "DB_USER is \$MYAPP_DB_USER" echo "DB_PASSWORD is \$MYAPP_DB_PASSWORD" java \ -Dspring.datasource.driver-class-name=\$MYAPP_DB_DRIVER \ -Dspring.datasource.url=\$MYAPP_DB_URL \ -Dspring.jpa.generate-ddl=true \ -Dspring.jpa.hibernate.ddl-auto=update \ -Dspring.datasource.username=\$MYAPP_DB_USER \ -Dspring.datasource.password=\$MYAPP_DB_PASSWORD \ -jar spring-app.war FIN ## Créer le dockerfile cat > web/Dockerfile <<FIN FROM my-java:latest LABEL desc="My SpringBoot App with MySql" WORKDIR /app ENV MYAPP_DB_DRIVER="com.mysql.jdbc.Driver" ENV MYAPP_DB_URL="jdbc:mysql://movies-app-database-1:3306/moviesdb" ENV MYAPP_DB_USER="moviesuser" ENV MYAPP_DB_PASSWORD="moviespass" ENV MYAPP_LOG="/var/tmp/myapp.log" ENV MYAPP_NAME="myapp" COPY spring-app.war /app/spring-app.war COPY start.sh /app/start.sh EXPOSE 8081 ENTRYPOINT ["/bin/bash", "/app/start.sh"] HEALTHCHECK --interval=4s --timeout=3s --retries=100 \ CMD curl -f http://localhost:8081/movies/ || exit 1 FIN
## Créer un répertoire pour les logs mkdir -p /var/movies/logs ## Créer le dockerfile cat > web.yaml <<FIN services: ## Services definition ## Partie WEB web: build: web ## deux instances scale: 2 expose: - "8081" restart: always ## Le WEB va attendre la BD depends_on: database: condition: service_healthy networks: - mynet ## Pour ne pas perdre les traces volumes: - /var/movies/logs/:/var/tmp FIN
## Lancer les services et attendre le statut healthy docker compose up -d --wait --build ## Lister les services docker compose ps ## Attendre les applications WEB - normalement inutile wait-for-healthy-container movies-app-web-1 600 wait-for-healthy-container movies-app-web-2 600 ## Tester les deux services docker run --network movies-app_mynet almalinux \ curl -sL movies-app-web-1:8081 | fgrep '1983' docker run --network movies-app_mynet almalinux \ curl -sL movies-app-web-2:8081 | fgrep '1983' ## Stopper les services docker compose rm --stop --force
La partie Front Proxy
Nous avons deux applications WEB qui fonctionnent en parallèle mais il faut maintenant ajouter un proxy qui va assurer le rôle de répartition des accès (load-balancing). Nous allons utiliser HAProxy.
## Préparer les fichiers de configuration de HAProxy wget http://tinyurl.com/jlmassat2/cca/proxy.zip unzip proxy.zip ## Preparer le fichier front.yaml cat > front.yaml <<FIN # Services definition services: ## La partie Proxy proxy: build: proxy/ ports: - 8888:80 restart: always networks: - mynet environment: DOMAIN_NAME: idl.xfr EMAIL_ADDRESS: root@idl.xfr BACKEND1_URL: movies-app-web-1:8081 BACKEND2_URL: movies-app-web-2:8081 depends_on: web: condition: service_healthy FIN
## Construire/Lancer/Attendre les services docker compose up -d --wait --build ## Lister les services docker compose ps
## Tester les services curl -L http://localhost:8888 | fgrep 'Star' ## Vérifier le round-robbin du proxy ## SERVERID doit indiquer une app. curl -i http://localhost:8888 ## SERVERID doit indiquer l'autre app. curl -i http://localhost:8888
## Stopper les services docker compose rm --stop --force