compose and K8s file cleanup (#273)

This commit is contained in:
Bret Fisher
2022-12-16 21:50:40 -05:00
committed by GitHub
parent f0fb81f707
commit 226edf0184
13 changed files with 139 additions and 509 deletions

View File

@@ -1,37 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vote", "vote\dotnet\Vote\Vote.csproj", "{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker", "worker\dotnet\Worker\Worker.csproj", "{083764E8-4C34-43FB-A468-F80CE0ADE10A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Result", "result\dotnet\Result\Result.csproj", "{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9687EAF5-BFF3-4F8D-9C78-1B8EE12CE091}.Release|Any CPU.Build.0 = Release|Any CPU
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{083764E8-4C34-43FB-A468-F80CE0ADE10A}.Release|Any CPU.Build.0 = Release|Any CPU
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9AD16D72-E3F5-4A76-814C-40EBD1EE7892}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9DEFC158-1225-4393-8A38-22256211D43D}
EndGlobalSection
EndGlobal

View File

@@ -1,50 +1,43 @@
Example Voting App
=========
# Example Voting App
A simple distributed application running across multiple Docker containers.
Getting started
---------------
## Getting started
Download [Docker Desktop](https://www.docker.com/products/docker-desktop) for Mac or Windows. [Docker Compose](https://docs.docker.com/compose) will be automatically installed. On Linux, make sure you have the latest version of [Compose](https://docs.docker.com/compose/install/).
Download [Docker Desktop](https://www.docker.com/products/docker-desktop) for Mac or Windows. [Docker Compose](https://docs.docker.com/compose) will be automatically installed. On Linux, make sure you have the latest version of [Compose](https://docs.docker.com/compose/install/).
This solution uses Python, Node.js, .NET, with Redis for messaging and Postgres for storage.
## Linux Containers
Run in this directory to build and run the app:
The Linux stack uses Python, Node.js, .NET Core, with Redis for messaging and Postgres for storage.
> If you're using [Docker Desktop on Windows](https://store.docker.com/editions/community/docker-ce-desktop-windows), you can run the Linux version by [switching to Linux containers](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers), or run the Windows containers version.
Run in this directory:
```
```shell
docker compose up
```
The app will be running at [http://localhost:5000](http://localhost:5000), and the results will be at [http://localhost:5001](http://localhost:5001).
The `vote` app will be running at [http://localhost:5000](http://localhost:5000), and the `results` will be at [http://localhost:5001](http://localhost:5001).
Alternately, if you want to run it on a [Docker Swarm](https://docs.docker.com/engine/swarm/), first make sure you have a swarm. If you don't, run:
```
```shell
docker swarm init
```
Once you have your swarm, in this directory run:
```
```shell
docker stack deploy --compose-file docker-stack.yml vote
```
## Run the app in Kubernetes
Run the app in Kubernetes
-------------------------
The folder k8s-specifications contains the YAML specifications of the Voting App's services.
The folder k8s-specifications contains the yaml specifications of the Voting App's services.
Run the following command to create the deployments and services objects in the vote namespace:
First create the vote namespace
```
$ kubectl create namespace vote
```
Run the following command to create the deployments and services objects:
```
$ kubectl create -f k8s-specifications/
```shell
kubectl create -f k8s-specifications/
vote "vote" created
deployment "db" created
deployment "db" created
service "db" created
deployment "redis" created
@@ -58,23 +51,20 @@ deployment "worker" created
The vote interface is then available on port 31000 on each host of the cluster, the result one is available on port 31001.
Architecture
-----
## Architecture
![Architecture diagram](architecture.png)
* A front-end web app in [Python](/vote) or [ASP.NET Core](/vote/dotnet) which lets you vote between two options
* A [Redis](https://hub.docker.com/_/redis/) or [NATS](https://hub.docker.com/_/nats/) queue which collects new votes
* A [.NET Core](/worker/) worker which consumes votes and stores them in…
* A [Postgres](https://hub.docker.com/_/postgres/) or [TiDB](https://hub.docker.com/r/dockersamples/tidb/tags/) database backed by a Docker volume
* A [Node.js](/result) or [ASP.NET Core SignalR](/result/dotnet) webapp which shows the results of the voting in real time
* A front-end web app in [Python](/vote) which lets you vote between two options
* A [Redis](https://hub.docker.com/_/redis/) which collects new votes
* A [.NET](/worker/) worker which consumes votes and stores them in…
* A [Postgres](https://hub.docker.com/_/postgres/) database backed by a Docker volume
* A [Node.js](/result) web app which shows the results of the voting in real time
## Notes
Notes
-----
The voting application only accepts one vote per client browser. It does not register additional votes if a vote has already been submitted from a client.
The voting application only accepts one vote per client. It does not register votes if a vote has already been submitted from a client.
This isn't an example of a properly architected perfectly designed distributed app... it's just a simple
example of the various types of pieces and languages you might see (queues, persistent data, etc), and how to
deal with them in Docker at a basic level.
This isn't an example of a properly architected perfectly designed distributed app... it's just a simple
example of the various types of pieces and languages you might see (queues, persistent data, etc), and how to
deal with them in Docker at a basic level.

View File

@@ -1,30 +0,0 @@
version: '3'
services:
redis:
image: redis:alpine
ports:
- "6379:6379"
db:
image: postgres:9.4
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
ports:
- "5432:5432"
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
deploy:
replicas: 1
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
worker:
image: dockersamples/examplevotingapp_worker
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"

View File

@@ -1,32 +0,0 @@
version: "3"
services:
vote:
build: ./vote
command: python app.py
volumes:
- ./vote:/app
ports:
- "5000:80"
redis:
image: redis:alpine
ports: ["6379"]
worker:
build: ./worker
db:
image: postgres:9.4
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
result:
build: ./result
command: nodemon server.js
volumes:
- ./result:/app
ports:
- "5001:80"
- "5858:5858"

70
docker-compose.images.yml Normal file
View File

@@ -0,0 +1,70 @@
# for running in docker compose with prebuilt images
# version is now using "compose spec"
# v2 and v3 are now combined!
# docker-compose v1.27+ required
services:
vote:
image: dockersamples/examplevotingapp_vote
depends_on:
redis:
condition: service_healthy
ports:
- "5000:80"
networks:
- front-tier
- back-tier
result:
image: dockersamples/examplevotingapp_result
depends_on:
db:
condition: service_healthy
ports:
- "5001:80"
networks:
- front-tier
- back-tier
worker:
image: dockersamples/examplevotingapp_worker
depends_on:
redis:
condition: service_healthy
db:
condition: service_healthy
networks:
- back-tier
redis:
image: redis:alpine
volumes:
- "./healthchecks:/healthchecks"
healthcheck:
test: /healthchecks/redis.sh
interval: "5s"
ports: ["6379"]
networks:
- back-tier
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
volumes:
- "db-data:/var/lib/postgresql/data"
- "./healthchecks:/healthchecks"
healthcheck:
test: /healthchecks/postgres.sh
interval: "5s"
networks:
- back-tier
volumes:
db-data:
networks:
front-tier:
back-tier:

View File

@@ -1,9 +0,0 @@
services:
seed:
build: ./seed-data
networks:
- front-tier
restart: "no"
networks:
front-tier:

View File

@@ -9,7 +9,13 @@ services:
command: python app.py
depends_on:
redis:
condition: service_healthy
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
volumes:
- ./vote:/app
ports:
@@ -46,7 +52,7 @@ services:
- back-tier
redis:
image: redis:5.0-alpine3.10
image: redis:alpine
volumes:
- "./healthchecks:/healthchecks"
healthcheck:
@@ -57,7 +63,7 @@ services:
- back-tier
db:
image: postgres:9.4
image: postgres:15-alpine
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
@@ -70,6 +76,19 @@ services:
networks:
- back-tier
# this service runs once to seed the database with votes
# it won't run unless you specify the "seed" profile
# docker compose --profile seed up -d
seed:
build: ./seed-data
profiles: ["seed"]
depends_on:
vote:
condition: service_healthy
networks:
- front-tier
restart: "no"
volumes:
db-data:

View File

@@ -1,84 +0,0 @@
version: "3"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- 5000:80
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 1
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- 5001:80
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
depends_on:
- db
- redis
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:

View File

@@ -1,19 +1,18 @@
version: "3"
# this file is meant for Docker Swarm stacks only
# trying it in compose will fail because of multiple replicas trying to bind to the same port
# Swarm currently does not support Compose Spec, so we'll pin to the older version 3.9
version: "3.9"
services:
redis:
image: redis:alpine
networks:
- frontend
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
image: postgres:15-alpine
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
@@ -21,69 +20,30 @@ services:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
image: dockersamples/examplevotingapp_vote
ports:
- 5000:80
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
image: dockersamples/examplevotingapp_result
ports:
- 5001:80
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
depends_on:
- db
- redis
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
replicas: 2
networks:
frontend:

View File

@@ -16,7 +16,7 @@ spec:
app: db
spec:
containers:
- image: postgres:9.4
- image: postgres:15-alpine
name: postgres
env:
- name: POSTGRES_USER

View File

@@ -16,7 +16,7 @@ spec:
app: result
spec:
containers:
- image: dockersamples/examplevotingapp_result:before
- image: dockersamples/examplevotingapp_result
name: result
ports:
- containerPort: 80

View File

@@ -16,7 +16,7 @@ spec:
app: vote
spec:
containers:
- image: dockersamples/examplevotingapp_vote:before
- image: dockersamples/examplevotingapp_vote
name: vote
ports:
- containerPort: 80

View File

@@ -1,217 +0,0 @@
# redis
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis
name: redis
spec:
clusterIP: None
ports:
- name: redis-service
port: 6379
targetPort: 6379
selector:
app: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
labels:
app: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
name: redis
# db
---
apiVersion: v1
kind: Service
metadata:
labels:
app: db
name: db
spec:
clusterIP: None
ports:
- name: db
port: 5432
targetPort: 5432
selector:
app: db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
labels:
app: db
spec:
replicas: 1
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: db
image: postgres:9.4
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
ports:
- containerPort: 5432
name: db
volumeMounts:
- name: db-data
mountPath: /var/lib/postgresql/data
volumes:
- name: db-data
persistentVolumeClaim:
claimName: postgres-pv-claim
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
# result
---
apiVersion: v1
kind: Service
metadata:
name: result
labels:
app: result
spec:
type: LoadBalancer
ports:
- port: 5001
targetPort: 80
name: result-service
selector:
app: result
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: result
labels:
app: result
spec:
replicas: 1
selector:
matchLabels:
app: result
template:
metadata:
labels:
app: result
spec:
containers:
- name: result
image: dockersamples/examplevotingapp_result:before
ports:
- containerPort: 80
name: result
# vote
---
apiVersion: v1
kind: Service
metadata:
name: vote
labels:
apps: vote
spec:
type: LoadBalancer
ports:
- port: 5000
targetPort: 80
name: vote-service
selector:
app: vote
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vote
labels:
app: vote
spec:
replicas: 2
selector:
matchLabels:
app: vote
template:
metadata:
labels:
app: vote
spec:
containers:
- name: vote
image: dockersamples/examplevotingapp_vote:before
ports:
- containerPort: 80
name: vote
# worker
---
apiVersion: v1
kind: Service
metadata:
labels:
apps: worker
name: worker
spec:
clusterIP: None
selector:
app: worker
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: worker
name: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
spec:
containers:
- image: dockersamples/examplevotingapp_worker
name: worker