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.