Création d'un network overlay
Mes deux applications, caddy et first_app, sont créées et n'ont plus qu'à être déployées sur mon cluster. Nous l'avons vu précédement, elles vont devoir partager un volume dans lequel sera présent le fichier d'entrée index.php
. Elle devront également partager le même réseau afin que first_app
puisse être définie avec php_fastcgi
sur notre configuration Caddy.
Le réseau s'appelera first_app_network
et le volume first_app
Dans le cas d'un cluster swarm, nous devons définir notre network
avec le driver overlay
afin que la communication s'effectue bien entre les noeuds de mon cluster.
Sur demo-swarm-1
, j'exécute donc la commande suivante :
docker network create --driver overlay first_app_network
Ajout dans mon projet Caddy d'un docker-compose.yaml
Dans ce fichier docker-compose.yaml
, je définis que mon service caddy
sera construit à partir de l'image caddy précédement construite.
version: '3.7'
services:
caddy:
image: ${CONTAINER_REGISTRY_BASE}/caddy:latest
networks:
# Mon service peut être associé à plusieurs networks. Pour commencer, il sera affecté à first_app_network
- first_app_network
volumes:
# Montage de volume. first_app sera accessible sur caddy sur /first_app
- first_app:/first_app
ports:
- 80:80
- 443:443
volumes:
first_app:
name: first_app
networks:
first_app_network:
# Bien définir le network en externe pour utiliser celui précédement créé
external: true
Et le .env associé
CONTAINER_REGISTRY_BASE=registry.gitlab.com/XXXXX/XXXXX
Ajout dans mon projet First App d'un docker-compose.yaml
version: '3.7'
services:
first_app:
image: ${CONTAINER_REGISTRY_BASE}/first_app:latest
volumes:
# Le volume first_app est monté sur /first_app_volume. Souvenez vous du docker-entrypoint.sh, c'est sur ce chemin que nous copions le contenu de public lors de la création du conteneur.
- first_app:/first_app_volume
networks:
# Bien sûr, nous utilisons le même network que celui défini précédement pour caddy
- first_app_network
deploy:
# Et vu que l'on utilise Swarm, on souhaite scaler notre application avec deux noeuds
mode: replicated
replicas: 2
resources:
# Et nous avons la possibilité avec Swarm de venir restreindre les ressources utilisées par notre service
# Et si on le souhaite, on peut même réserver de la ressource pour un service
limits:
cpus: '0.5'
memory: 500M
volumes:
first_app:
name: first_app
networks:
first_app_network:
external: true
Et le .env associé
CONTAINER_REGISTRY_BASE=registry.gitlab.com/XXXXX/XXXXX
Déployons tout ça !
Pour commencer, je vais m'occuper du serveur Caddy.
eval $(docker-machine env demo-swarm-1)
export $(cat .env | xargs)
docker stack deploy --with-registry-auth -c docker-compose.yaml caddy
Et ensuite, la même chose pour first_app
eval $(docker-machine env demo-swarm-1)
export $(cat .env | xargs)
docker stack deploy --with-registry-auth -c docker-compose.yaml first_app
Maintenant quelques commandes pour regarder l'état de mes services.
Cette première commande va nous permettre de lister nos services
docker service ls
docker service ps first_app_first_app
Je constate ici que mon service est bien répliqué sur les deux noeuds qui constituent mon cluster. Pour une visualisation plus graphique, je peux utiliser dockersamples/visualizer
docker service create \
--name=viz \
--publish=8080:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer
Vous devez bien sûr autoriser le port 8080 pour l'IP de votre machine sur demo-swarm-1
sudo ufw route allow proto tcp from MON_IP to any port 8080
sudo ufw enable
Je peux maintenant accéder à ma first_app via son nom de domaine. Je vois ainsi comment le load balancing de swarm fonctionne. Il passe simplement d'une instance à une autre.
Est-ce satisfaisant ?
On peut le dire, cela fonctionne très bien. Mais concernant l'ajout dynamique d'un domaine, ce n'est pas encore ça. Il faudrait que je sois capable via un montage volume de mettre à jour facilement le Caddyfile
.
Une fois à jour, il faudrait que je trouve un moyen d'appeler l'API de Caddy pour recharger ma configuration.
curl "http://localhost:2019/load" \
-H "Content-Type: text/caddyfile" \
--data-binary @Caddyfile
Rien de bien compliqué en soit. En fait, ce qui me gène le plus, c'est le partage de volume entre Caddy et mon application PHP. C'est parfait pour l'exemple, mais je trouve qu'une architecture plus durable serait de mettre en place Caddy en tant que proxy uniquement. Il serait donc chargé de faire passe plat uniquement vers un varnish ou un caddy configuré pour servir du PHP.
Et ça tombe bien, car c'est le sujet du dernier article de cette série !