Przeglądaj źródła

compose and K8s file cleanup (#273)

Bret Fisher 2 lat temu
rodzic
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.
 
-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.
 
-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
 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. 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
     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:
 

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

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

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

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

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

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

@@ -16,7 +16,7 @@ spec:
         app: vote
     spec:
       containers:
-      - image: dockersamples/examplevotingapp_vote:before
+      - image: dockersamples/examplevotingapp_vote
         name: vote
         ports:
         - 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