FONCTIONNEMENT
Voting app est une application contenant 5 services :
- voting-app : application Web écrite en Python
- redis : base de données Redis
- worker : worker écrit en .NET
- db : base de données PostgreSQL
- result-app: application Web écrite en Javascript (Node.js)
Principe :
- voting-app : Un utilisateur vote depuis l’interface Web fournie par le service de vote. Il doit choisir entre un chien et un chat.
- redis : Le vote est stocké dans la base de données Redis.
- worker : Le service worker récupère le vote depuis la base de données Redis.
- db : Le service worker enregistre le vote dans la base de données des résultats gérée par PostgreSQL.
- result-app : Les utilisateurs ont accès aux résultats via l’interface Web dédiée.
L’interface front-end de vote (service vote) se trouve sur le port 5000, mappé sur le port 80 du container :
http://localhost:5000
Il suffit de cliquer sur cats ou dogs pour voter :
L’interface front-end des résultats (service result) se trouve sur le port 5001, mappé sur le port 80 du container :
http://localhost:5001
FICHIER DOCKER COMPOSE
version: "3" services: vote: build: ./vote command: python app.py volumes: - ./vote:/app ports: - "5000:80" networks: - front-tier - back-tier result: build: ./result command: nodemon server.js volumes: - ./result:/app ports: - "5001:80" - "5858:5858" networks: - front-tier - back-tier worker: build: context: ./worker depends_on: - "redis" networks: - back-tier redis: image: redis:alpine container_name: redis ports: ["6379"] networks: - back-tier db: image: postgres:9.4 container_name: db volumes: - "db-data:/var/lib/postgresql/data" networks: - back-tier volumes: db-data: networks: front-tier: back-tier:
Lancement de l’application en arrière-plan :
$ docker-compose up -d
Ce qui génère 5 services (un container par service) :
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b13c10150570 example-voting-app_worker "/bin/sh -c 'dotnet …" 42 minutes ago Up 6 minutes example-voting-app_worker_1
23001995c218 example-voting-app_result "nodemon server.js" 42 minutes ago Up 6 minutes 0.0.0.0:5858->5858/tcp, 0.0.0.0:5001->80/tcp example-voting-app_result_1
df80fc1ede35 redis:alpine "docker-entrypoint.s…" 42 minutes ago Up 6 minutes 0.0.0.0:32769->6379/tcp redis
b0af9be2079f postgres:9.4 "docker-entrypoint.s…" 42 minutes ago Up 6 minutes 5432/tcp db
0b22e1d1ae49 example-voting-app_vote "python app.py" 42 minutes ago Up 6 minutes 0.0.0.0:5000->80/tcp example-voting-app_vote_1
On obtient un état des lieux similaires avec la commande docker-compose dédiée :
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------
db docker-entrypoint.sh postgres Up 5432/tcp
example-voting-app_result_1 nodemon server.js Up 0.0.0.0:5858->5858/tcp, 0.0.0.0:5001->80/tcp
example-voting-app_vote_1 python app.py Up 0.0.0.0:5000->80/tcp
example-voting-app_worker_1 /bin/sh -c dotnet src/Work ... Up
redis docker-entrypoint.sh redis ... Up 0.0.0.0:32769->6379/tcp
FICHIER DOCKER STACK
version: "3" services: redis: image: redis:alpine ports: - "6379" networks: - frontend deploy: replicas: 1 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data networks: - backend deploy: placement: constraints: [node.role == manager] vote: image: dockersamples/examplevotingapp_vote:before ports: - 5000:80 networks: - frontend depends_on: - redis deploy: replicas: 2 update_config: parallelism: 2 restart_policy: condition: on-failure result: image: dockersamples/examplevotingapp_result:before ports: - 5001:80 networks: - backend depends_on: - db deploy: replicas: 1 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure worker: image: dockersamples/examplevotingapp_worker networks: - frontend - backend deploy: mode: replicated replicas: 1 labels: [APP=VOTING] restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s placement: constraints: [node.role == manager] visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: frontend: backend: volumes: db-data:
Lancement de la stack :
Ici nous déployons 6 services répartis en 7 tâches exécutées sur 3 nodes composant le cluster swarm.
$ docker stack deploy -c docker-stack.yml mystack
Creating network mystack_frontend
Creating network mystack_backend
Creating network mystack_default
Creating service mystack_visualizer
Creating service mystack_redis
Creating service mystack_db
Creating service mystack_vote
Creating service mystack_result
Creating service mystack_worker
On peut afficher la stack ainsi déployée :
$ docker stack ls
NAME SERVICES ORCHESTRATOR
mystack 6 Swarm
On peut ensuite visualiser la répartition des tâches sur les différents nodes du cluster swarm :
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
kn1qdmquzz1r mystack_db replicated 1/1 postgres:9.4
xt2mwakr6u66 mystack_redis replicated 1/1 redis:alpine *:30001->6379/tcp
3qi1rdmocngh mystack_result replicated 1/1 dockersamples/examplevotingapp_result:before *:5001->80/tcp
xehxo13zisbz mystack_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp
ryq7lsbz944j mystack_vote replicated 2/2 dockersamples/examplevotingapp_vote:before *:5000->80/tcp
q2onk7lai1xc mystack_worker replicated 1/1 dockersamples/examplevotingapp_worker:latest