Welcome to your DevOps practice project! This repository hosts a multi-stack voting application composed of several services, each implemented in a different language and technology stack. The goal is to help you gain experience with containerization, orchestration, and running a distributed set of services—both individually and as part of a unified system.
This application, while simple, uses multiple components commonly found in modern distributed architectures, giving you hands-on practice in connecting services, handling containers, and working with basic infrastructure automation.
The voting application includes:
- Vote (Python): A Python Flask-based web application where users can vote between two options.
- Redis (in-memory queue): Collects incoming votes and temporarily stores them.
- Worker (.NET): A .NET 7.0-based service that consumes votes from Redis and persists them into a database.
- Postgres (Database): Stores votes for long-term persistence.
- Result (Node.js): A Node.js/Express web application that displays the vote counts in real time.
The goal is to introduce you to a variety of languages, tools, and frameworks in one place. This is not a perfect production design. Instead, it’s intentionally diverse to help you:
- Work with multiple runtimes and languages (Python, Node.js, .NET).
- Interact with services like Redis and Postgres.
- Containerize applications using Docker.
- Use Docker Compose to orchestrate and manage multiple services together.
By dealing with this “messy” environment, you’ll build real-world problem-solving skills. After this project, you should feel more confident tackling more complex deployments and troubleshooting issues in containerized, multi-service setups.
- Ensure you have Python 3.10+ installed.
- Navigate to the
vote
directory:Access the vote interface at http://localhost:5000.cd vote pip install -r requirements.txt python app.py
- Install Redis on your system (https://redis.io/docs/getting-started/).
- Start Redis:
Redis will be available at
redis-server
localhost:6379
.
- Ensure .NET 7.0 SDK is installed.
- Navigate to
worker
:The worker will attempt to connect to Redis and Postgres when available.cd worker dotnet restore dotnet run
- Install Postgres from https://www.postgresql.org/download/.
- Start Postgres, note the username and password (default
postgres
/postgres
):Postgres will be available at# On many systems, Postgres runs as a service once installed.
localhost:5432
.
- Ensure Node.js 18+ is installed.
- Navigate to
result
:Access the results interface at http://localhost:4000.cd result npm install node server.js
Note: To get the entire system working end-to-end (i.e., votes flowing through Redis, processed by the worker, stored in Postgres, and displayed by the result app), you’ll need to ensure each component is running and that connection strings or environment variables point to the correct services.
You can build each service with Docker and run them individually:
-
Vote (Python):
docker build -t myorg/vote:latest ./vote docker run --name vote -p 8080:80 myorg/vote:latest
Visit http://localhost:8080.
-
Redis (official image, no build needed):
docker run --name redis -p 6379:6379 redis:alpine
-
Worker (.NET):
docker build -t myorg/worker:latest ./worker docker run --name worker myorg/worker:latest
-
Postgres:
docker run --name db -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:15-alpine
-
Result (Node.js):
docker build -t myorg/result:latest ./result docker run --name result -p 8081:80 myorg/result:latest
Visit http://localhost:8081.
The easiest way to run the entire stack is via Docker Compose. From the project root directory:
docker compose up
This will:
- Build and run the vote, worker, and result services.
- Run Redis and Postgres from their official images.
- Set up networks, volumes, and environment variables so all services can communicate.
Visit http://localhost:8080 to vote and http://localhost:8081 to see results.
If you’re on an arm64 machine (e.g., Apple Silicon M1/M2) and encounter issues with images or dependencies that assume amd64, you can use Docker buildx
:
docker buildx build --platform linux/amd64 -t myorg/worker:latest ./worker
This ensures the image is built for the desired platform.