Playground avec Voting App

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 :

  1. voting-app : Un utilisateur vote depuis l’interface Web fournie par le service de vote. Il doit choisir entre un chien et un chat.
  2. redis : Le vote est stocké dans la base de données Redis.
  3. worker : Le service worker récupère le vote depuis la base de données Redis.
  4. db : Le service worker enregistre le vote dans la base de données des résultats gérée par PostgreSQL.
  5. 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

 

REFERENCES

GitHub – dockersamples/example-voting-app