Skip to main content
This guide walks through the example voting application: its architecture, each service’s role and source layout, and how to build and run the full stack locally with Docker. The demo uses a small Flask front end, a Node.js real-time dashboard, a .NET worker, Redis as a queue, and Postgres as durable storage. Repository overview
  • The stack has five components: vote (Flask), result (Node.js + Socket.IO), worker (C#/.NET), redis (queue), and postgres (database).
  • App code for the three services is included in the repo under vote/, result/, and worker/. Redis and Postgres are pulled from public images.
Architecture diagram
Screenshot of a code editor's file explorer (VS Code) showing an "example-voting-app" project with architecture.excalidraw.png selected. The right side shows part of a system diagram including a "vote" box and a Python logo.
Components — quick tour
  1. vote (Flask)
  • A lightweight Flask app presents two options (e.g., Cats vs Dogs).
  • On submit, it generates a voter_id, pushes a JSON payload into Redis (list votes), and sets a cookie for the client.
  • The app listens on port 80 and is served by Gunicorn in the production image.
Key parts of the Flask application (simplified):
Multi-stage Dockerfile pattern (vote)
  • The example Dockerfile uses multi-stage builds to install dependencies in a base image, provide a development stage with file-watching, and produce a small runnable final image served by Gunicorn.
  1. worker (C#)
  • The worker polls Redis votes, processes each vote (e.g., de-duplicates or aggregates), and stores results in Postgres.
  • It connects to Redis at host redis and Postgres at host db using credentials in the demo.
Relevant C# snippet (simplified):
Example multi-stage Dockerfile for the worker (.NET):
  1. result (Node.js)
  • The result service is a Node.js/Socket.IO server that reads aggregated state from Postgres and pushes updates to connected browsers in real time.
  • It uses a Postgres connection string pointing to host db with user postgres and password postgres (demo configuration).
Key server snippet:
Example Dockerfile for the result app (Node):
Important note about credentials
This demo embeds Postgres credentials and connection strings directly in source code for simplicity. For production, always inject secrets via environment variables, a secrets manager, or your orchestration platform (e.g., Docker secrets, Kubernetes Secrets, HashiCorp Vault).
Build and run locally with Docker (step-by-step)
  • From the repository root you can either build each service image manually or use docker compose up if the repository includes a Compose file.
Build images (if not using Compose):
Create a user-defined bridge network so containers can reach each other by name:
Start Redis and Postgres (Postgres uses a named volume for persistence):
Run the application containers and attach them to the voting-app network:
Verify containers are running:
Ports and endpoints What to expect
  • Use the Vote UI to cast votes. The Flask app enqueues messages in Redis.
  • The worker polls Redis, processes votes, and writes aggregated results to Postgres.
  • The Result UI reads from Postgres and broadcasts updates to clients in real time via Socket.IO.
Cleanup (optional)
  • Stop and remove containers, the network, and the volume:
That covers the local build-and-run workflow for the example voting application. For production deployment, move secrets out of source, use proper healthchecks and readiness probes, and consider orchestration with Docker Compose, Kubernetes, or another platform.

Watch Video