Skip to main content
Welcome to this guide on deploying the example voting application from the Docker samples repository. This demo showcases a multi-container application architecture using Docker, featuring several components. In this article, we review the application’s design, examine source code segments, and deploy the application using Docker commands. Later, we will expand this demo to incorporate Docker Compose, Docker Stacks, and Swarm services.

Overview

The voting application is composed of the following components:
  • A Python-based voting application (using Flask) that presents a web page for casting votes.
  • A Redis messaging service that temporarily stores votes.
  • A Java-based worker application that processes votes from Redis and updates a PostgreSQL database.
  • A Node.js-powered results application that queries PostgreSQL and displays real-time voting results.
Redis and PostgreSQL utilize official Docker Hub images, while the voting app, worker, and results components are custom-developed. Below is the architecture diagram that illustrates the interaction between these components:
The image is a diagram of a voting app architecture using Python, Node.js, Redis, PostgreSQL, and .NET, showing the interaction between components.

The Voting Application

The repository organizes the custom applications into distinct folders. Let’s begin by exploring the voting application. Within the vote directory, the Flask application is defined in the file app.py. The application handles both GET and POST requests. In a GET request, it renders the main page (index.html), while the POST handler processes the vote by pushing vote data to Redis. Below is an example of the Python code for the voting application:
In the vote directory, you will also find the Dockerfile, which builds the voting application image. This Dockerfile uses the Python 2.7 Alpine image, installs dependencies from requirements.txt, copies the source code, exposes port 80, and runs the application using Gunicorn.
Click on the vote directory in the repository to view files such as app.py and the Dockerfile. This overview helps in understanding how the application components are organized.
Below is a GitHub screenshot showing the repository page for the voting application with files like Dockerfile and app.py:
The image shows a GitHub repository page for "example-voting-app," displaying files like Dockerfile and app.py in the "vote" directory.

The Worker Application

The worker is located in the worker folder. This Java-based application connects to Redis and PostgreSQL. It monitors Redis for new votes using a blocking pop operation. When a vote is received, the worker updates the PostgreSQL database. Here is a snippet of the Java code for the worker:
The corresponding Dockerfile for the worker uses the Microsoft .NET SDK image. It copies the source code, restores dependencies, publishes the application, and sets the startup command.
Even though the code uses hostnames “redis” and “db” for connectivity, ensure that corresponding containers or network links are available at runtime.

The Results Application

The results application, implemented with Node.js and Express, connects to PostgreSQL to fetch vote counts. It also uses websockets to emit live score updates to client browsers. Below is an excerpt from its server.js file:
The Dockerfile for the results app is based on a slim Node.js image. It installs dependencies from package.json, sets up the working directory, and starts the Node.js server on port 80.
The overall architecture including the results application is illustrated in the following diagram:
The image shows a system architecture diagram for a voting app using Python, Node.js, Redis, PostgreSQL, and .NET components.

Deployment Walkthrough

Cloning the Repository

Begin by cloning the repository to your local system:
Change into the repository directory:

Building and Running the Voting Application

  1. Navigate to the vote directory to inspect its contents:
    You should see files such as app.py, Dockerfile, and the directories static and templates.
  2. View the Dockerfile to confirm its contents:
  3. Build the Docker image for the voting application:
  4. Run the voting application container by mapping host port 5000 to container port 80:
Open your browser and navigate to http://localhost:5000. You should see two options for casting your vote (for example, “Cats” and “Dogs”). Casting a vote without Redis running may result in a timeout error in the logs.

Starting Redis

To provide a backend for votes, start a Redis container. If a container named “redis” exists, remove it first:
Launch Redis (detached mode is recommended):
Run the voting application container again while linking to the Redis container:
With Redis running and linked, casting a vote should successfully store the vote. A confirmation (often indicated by a tick mark) will be visible.

Deploying PostgreSQL for Worker and Results Applications

The worker and results applications depend on a PostgreSQL database. It is recommended to use PostgreSQL 9.4. If a container named “db” is running, remove it:
Start PostgreSQL in detached mode:
Verify the container is active:

Building and Running the Worker Application

  1. Navigate to the worker directory to inspect the source code and Dockerfile.
  2. Build the worker image:
  3. Run the worker container, linking both Redis and the PostgreSQL database:
The worker will now continuously process votes from Redis and update the PostgreSQL database.

Building and Running the Results Application

  1. Change to the result directory:
  2. View the Dockerfile to ensure correctness:
  3. Build the results application image:
  4. Run the results container, linking it to PostgreSQL and mapping host port 5001 to container port 80:
When you open your browser and visit http://localhost:5001, the results page displays the current vote counts. Any voting change registered by the voting application is processed by the worker and reflected on this page. Below is an image showing a sample voting result:
The image shows a voting result with "Cats" at 100% and "Dogs" at 0%, based on one vote.

Summary

In this guide we have:
  • Explored the architecture of the example voting application.
  • Reviewed the Flask-based voting app that accepts votes and pushes them to Redis.
  • Examined the Java worker which processes votes from Redis and updates PostgreSQL.
  • Analyzed the Node.js results app that queries PostgreSQL and displays real-time results.
  • Built and deployed each component individually using Docker commands and container linking.
In the next article, we will demonstrate how to orchestrate this multi-container setup with Docker Compose for simplified management. Happy Dockering!

Watch Video