Browse Source

compose and K8s file cleanup (#273)

Bret Fisher 2 years ago
parent
commit
226edf0184

+ 0 - 37
ExampleVotingApp.sln

@@ -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

+ 31 - 41
README.md

@@ -1,50 +1,43 @@
-Example Voting App
-=========
+# Example Voting App
 
 
 A simple distributed application running across multiple Docker containers.
 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
 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:
 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
 docker swarm init
 ```
 ```
+
 Once you have your swarm, in this directory run:
 Once you have your swarm, in this directory run:
-```
+
+```shell
 docker stack deploy --compose-file docker-stack.yml vote
 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.
 
 
-First create the vote namespace
-
-```
-$ kubectl create namespace vote
-```
+Run the following command to create the deployments and services objects in the vote namespace:
 
 
-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
 deployment "db" created
 service "db" created
 service "db" created
 deployment "redis" 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.
 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)
 ![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. It does not register votes if a vote has already been submitted from a client.
+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.
 
 
-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.

+ 0 - 30
docker-compose-k8s.yml

@@ -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"

+ 0 - 32
docker-compose-simple.yml

@@ -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 - 0
docker-compose.images.yml

@@ -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:

+ 0 - 9
docker-compose.seed.yml

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

+ 22 - 3
docker-compose.yml

@@ -9,7 +9,13 @@ services:
     command: python app.py
     command: python app.py
     depends_on:
     depends_on:
       redis:
       redis:
-        condition: service_healthy 
+        condition: service_healthy
+    healthcheck: 
+      test: ["CMD", "curl", "-f", "http://localhost"]
+      interval: 15s
+      timeout: 5s
+      retries: 3
+      start_period: 10s
     volumes:
     volumes:
      - ./vote:/app
      - ./vote:/app
     ports:
     ports:
@@ -46,7 +52,7 @@ services:
       - back-tier
       - back-tier
 
 
   redis:
   redis:
-    image: redis:5.0-alpine3.10
+    image: redis:alpine
     volumes:
     volumes:
       - "./healthchecks:/healthchecks"
       - "./healthchecks:/healthchecks"
     healthcheck:
     healthcheck:
@@ -57,7 +63,7 @@ services:
       - back-tier
       - back-tier
 
 
   db:
   db:
-    image: postgres:9.4
+    image: postgres:15-alpine
     environment:
     environment:
       POSTGRES_USER: "postgres"
       POSTGRES_USER: "postgres"
       POSTGRES_PASSWORD: "postgres"
       POSTGRES_PASSWORD: "postgres"
@@ -70,6 +76,19 @@ services:
     networks:
     networks:
       - back-tier
       - 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:
 volumes:
   db-data:
   db-data:
 
 

+ 0 - 84
docker-stack-simple.yml

@@ -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:

+ 13 - 53
docker-stack.yml

@@ -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:
 services:
 
 
   redis:
   redis:
     image: redis:alpine
     image: redis:alpine
     networks:
     networks:
       - frontend
       - frontend
-    deploy:
-      replicas: 1
-      update_config:
-        parallelism: 2
-        delay: 10s
-      restart_policy:
-        condition: on-failure
+
   db:
   db:
-    image: postgres:9.4
+    image: postgres:15-alpine
     environment:
     environment:
       POSTGRES_USER: "postgres"
       POSTGRES_USER: "postgres"
       POSTGRES_PASSWORD: "postgres"
       POSTGRES_PASSWORD: "postgres"
@@ -21,69 +20,30 @@ services:
       - db-data:/var/lib/postgresql/data
       - db-data:/var/lib/postgresql/data
     networks:
     networks:
       - backend
       - backend
-    deploy:
-      placement:
-        constraints: [node.role == manager]
+
   vote:
   vote:
-    image: dockersamples/examplevotingapp_vote:before
+    image: dockersamples/examplevotingapp_vote
     ports:
     ports:
       - 5000:80
       - 5000:80
     networks:
     networks:
       - frontend
       - frontend
-    depends_on:
-      - redis
     deploy:
     deploy:
       replicas: 2
       replicas: 2
-      update_config:
-        parallelism: 2
-      restart_policy:
-        condition: on-failure
+
   result:
   result:
-    image: dockersamples/examplevotingapp_result:before
+    image: dockersamples/examplevotingapp_result
     ports:
     ports:
       - 5001:80
       - 5001:80
     networks:
     networks:
       - backend
       - backend
-    depends_on:
-      - db
-    deploy:
-      replicas: 1
-      update_config:
-        parallelism: 2
-        delay: 10s
-      restart_policy:
-        condition: on-failure
 
 
   worker:
   worker:
     image: dockersamples/examplevotingapp_worker
     image: dockersamples/examplevotingapp_worker
     networks:
     networks:
       - frontend
       - frontend
       - backend
       - 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:
     deploy:
-      placement:
-        constraints: [node.role == manager]
+      replicas: 2
 
 
 networks:
 networks:
   frontend:
   frontend:

+ 1 - 1
k8s-specifications/db-deployment.yaml

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

+ 1 - 1
k8s-specifications/result-deployment.yaml

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

+ 1 - 1
k8s-specifications/vote-deployment.yaml

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

+ 0 - 217
kube-deployment.yml

@@ -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