Docker Compose exercise: voting App

Posted by dhimok on Tue, 25 Jan 2022 01:22:18 +0100

Docker Compose classic example: Example Voting App

GitHub address: https://github.com/dockersamples/example-voting-app

For students with poor network, I have downloaded the source code, address: https://download.csdn.net/download/weixin_48447848/77354937

Example Voting App

Simple distributed applications running across multiple Docker containers.

preparation in advance

Download Docker Desktop for Mac or Windows. Docker Compose will be installed automatically. On Linux, make sure you have the latest version of Compose.

Linux container example

Linux stack uses Python, node js,. NET Core (or optional Java) uses Redis for message delivery and Postgres for storage.

If you use Docker Desktop on Windows, you can run the Linux version or the Windows container version by switching to the Linux container.

Run in this directory:

docker-compose up

The application will http://localhost:5000 Run, the results will be http://localhost:5001 .

Or, if you want to run it on Docker Swarm, first make sure you have a swarm. If not, run:

docker swarm init

Once you have your swarm, run it in this directory:

docker stack deploy --compose-file docker-stack.yml vote

Start the operation again

Download source code: https://download.csdn.net/download/weixin_48447848/77354937

View and explain

example-voting-app/docker-compose.yml

Analysis content:
There are a total of 5 containers to create:

  • vote voting service
  • result view voting results in the background
  • worker consuming vote service
  • redis is used for message queuing
  • db database

volumes: Mount storage space DB data

Networks: two docker networks, front tier and back tier

# version is now using "compose spec"
# v2 and v3 are now combined!
# docker-compose v1.27+ required

services:
  vote:
    build: ./vote
    # use python rather than gunicorn for local dev
    command: python app.py
    depends_on:
      redis:
        condition: service_healthy  # The void service depends on the redis health status
    volumes:
     - ./vote:/app
    ports:
      - "5000:80"
    networks:
      - front-tier
      - back-tier

  result:
    build: ./result
    # use nodemon rather than node for local dev
    command: nodemon server.js
    depends_on:
      db:
        condition: service_healthy  # The result service depends on the health status of the db database
    volumes:
      - ./result:/app
    ports:
      - "5001:80"
      - "5858:5858"
    networks:
      - front-tier
      - back-tier

  worker:
    build:
      context: ./worker
    depends_on:
      redis: # The worker service depends on redis and DB health status
        condition: service_healthy  
      db:
        condition: service_healthy 
    networks:
      - back-tier

  redis:
    image: redis:5.0-alpine3.10
    volumes:
      - "./healthchecks:/healthchecks"
    healthcheck:
      test: /healthchecks/redis.sh # Detect the script and execute it every five seconds
      interval: "5s"
    ports: ["6379"]
    networks:
      - back-tier

  db:
    image: postgres:9.4
    environment:
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "postgres"
    volumes:
      - "db-data:/var/lib/postgresql/data"
      - "./healthchecks:/healthchecks"
    healthcheck:
      test: /healthchecks/postgres.sh # Health detection script
      interval: "5s"
    networks:
      - back-tier

volumes:
  db-data:

networks:
  front-tier:
  back-tier:

example-voting-app/vote/Dockerfile

Front desk voting service

# Using official python runtime base image
FROM python:3.9-slim

# add curl for healthcheck
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Set the application directory
WORKDIR /app

# Install our requirements.txt
COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt

# Copy our code from the current folder to /app inside the container
COPY . .

# Make port 80 available for links and/or publish
EXPOSE 80

# Define our command to be run when launching the container
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:80", "--log-file", "-", "--access-logfile", "-", "--workers", "4", "--keep-alive", "0"] 

example-voting-app/result/Dockerfile

View the voting results in the background, node Dockerfile of JS service

FROM node:10-slim

# add curl for healthcheck
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Add Tini for proper init of signals
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini

WORKDIR /app # Enter app directory

# have nodemon available for local dev use (file watching)
RUN npm install -g nodemon

COPY package*.json ./

RUN npm ci \
 && npm cache clean --force \
 && mv /app/node_modules /node_modules

COPY . .  # Copy the code from the current folder to / app in the container

ENV PORT 80

EXPOSE 80

CMD ["/tini", "--", "node", "server.js"]

example-voting-app/worker/Dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as builder

WORKDIR /Worker
COPY src/Worker/Worker.csproj .
RUN dotnet restore

COPY src/Worker/ .
RUN dotnet publish -c Release -o /out Worker.csproj

# app image
FROM mcr.microsoft.com/dotnet/core/runtime:3.1

WORKDIR /app
ENTRYPOINT ["dotnet", "Worker.dll"]

COPY --from=builder /out .

Health detection script example voting app / healthchecks/

postgres.sh database service detection script

#!/bin/bash
set -eo pipefail

host="$(hostname -i || echo '127.0.0.1')"
user="${POSTGRES_USER:-postgres}"
db="${POSTGRES_DB:-$POSTGRES_USER}"
export PGPASSWORD="${POSTGRES_PASSWORD:-}"

args=(
	# force postgres to not use the local unix socket (test "external" connectibility)
	--host "$host"
	--username "$user"
	--dbname "$db"
	--quiet --no-align --tuples-only
)

if select="$(echo 'SELECT 1' | psql "${args[@]}")" && [ "$select" = '1' ]; then
	exit 0
fi

exit 1

redis.sh detection script

#!/bin/sh
set -eo pipefail

host="$(hostname -i || echo '127.0.0.1')"

if ping="$(redis-cli -h "$host" ping)" && [ "$ping" = 'PONG' ]; then
	exit 0
fi

exit 1

implement

Select docker - compose YML file

docker-compose -f .\docker-compose.yml up -d

Wait for pull and build, hundreds of lines of input, omit

View container creation

PS C:\Users\Cypress fir\Downloads\example-voting-app-master> docker-compose ps
               Name                             Command                  State                      Ports               
------------------------------------------------------------------------------------------------------------------------
example-voting-app-master_db_1       docker-entrypoint.sh postgres    Up (healthy)   5432/tcp                           
example-voting-app-master_redis_1    docker-entrypoint.sh redis ...   Up (healthy)   0.0.0.0:3161->6379/tcp             
example-voting-app-master_result_1   docker-entrypoint.sh nodem ...   Up             0.0.0.0:5858->5858/tcp,            
                                                                                     0.0.0.0:5001->80/tcp               
example-voting-app-master_vote_1     python app.py                    Up             0.0.0.0:5000->80/tcp               
example-voting-app-master_worker_1   dotnet Worker.dll                Up                                                
PS C:\Users\Cypress fir\Downloads\example-voting-app-master>

Port 5000 voting service
View voting results on port 5001

Access browser http://127.0.0.1:5000/ Vote.
The same IP and browser are considered as one user. You can't vote repeatedly. You can open several different browsers, such as Chrome, Firefox, Edge, etc


Access browser http://127.0.0.1:5001/ View the voting results.
CATS and DOGS, one for each effect:

Architecture

  • A Python or ASP Net core allows you to vote between two options
  • A Redis or NATS message queue used to collect new votes
  • One NET Core, Java or NET Core 2.1, Worker consumes votes and stores them in
  • A database that uses Docker volume to mount Postgres or TiDB
  • A node js or ASP. Net core signalr Web App that displays voting results in real time

be careful

The voting application accepts only one vote per customer. If the customer has submitted a vote, it will not register to vote.

This is not a reasonably structured and well-designed distributed App example... It is just a simple example of various types of fragments and languages (queues, persistent data, etc.) and how to process them in Docker.

Topics: Linux Operation & Maintenance Docker docker compose