Skip to content

Commit 268eccb

Browse files
committed
Added Postgres as an additional persistency layer (as well as some cosmetic changes to the app UI)
1 parent 56ce32e commit 268eccb

File tree

18 files changed

+270
-93
lines changed

18 files changed

+270
-93
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ Yelb is an app I wrote from scratch (leveraging existing frameworks and tools su
66
I have built it for a couple of reasons:
77

88
- while there are dozens of demo/test apps out there, I think that having an app that you know 100% end-to-end and that you know inside out is something useful (if nothing, you will learn/experience one or more programming languages)
9-
- building a set of assets to deploy the application on multiple platforms (e.g. Docker, Kubernetes, Rancher, CloudFoundry, OpenShift, ECS, etc etc). Owning the application itself makes this task easier, more useful and more interesting.
9+
- building a set of assets to deploy a "real" application on multiple platforms (e.g. Docker, Kubernetes, Rancher, CloudFoundry, OpenShift, ECS, Serverless etc etc). Owning the application itself makes this task easier, more useful and more interesting. Also, using target platforms specific examples isn't quite like the challenge of having to think about how to adapt an existing application to be able to deploy it on a specific target platform.
1010

11-
As far as reason #1 goes, I found very interesting dealing with the challenges (at the edge of dev and ops duties) of starting and coordinating the application modules in specific environments (development, test, production). This is often achieved in specific programming environments leveraging system variables (e.g. RACK_ENV for ruby, other mechanisms for Angular2, etc). You will see some of these configurations in actions in the `localdevelopment` and `localtest` instructions (inside the `deployments` folder). Building an application from scratch and packaging it using Docker while honoring this flexibility is a very interesting (learning) exercise.
11+
As far as reason #1 goes, I found very interesting dealing with the challenges (at the edge of dev and ops duties) of starting and coordinating the application modules in specific environments (development, test, production). This is often achieved in specific programming environments leveraging system variables (e.g. RACK_ENV for ruby, other mechanisms for Angular2, etc). You will see some of these configurations in actions in the `localdevelopment` and `localtest` instructions (inside the `deployments` folder). Building an application from scratch and packaging it using Docker while honoring this flexibility is a very interesting (learning) exercise.
1212

1313
#### Yelb architecture
1414

1515
The current architecture layout is pretty straightforward.
1616

1717
There is a front-end component called `yelb-ui` that fullfills a couple of roles (they could even be split if need be). The first role is to host the Angular 2 application (i.e. the UI of the Yelb application). When the browser connects to this layer it downloads the `Javascript` code that builds the UI itself. Subsequent requests and calls to other application components are proxied via the `nginx` service running on `yelb-ui`.
1818

19-
At the time of this writing the only application component that exists is `yelb-appserver`. This is a Sinatra application that basically read and write to a third component which is the `redis-server` backend database (the third component of the Yelb application). At this point Redis is used more as a backend data base than as a memory cache. In the future it may be possible to insert a true backend system (e.g. Mongo) to store "transactional" data and keep using Redis for storing less critical information.
19+
At the time of this writing the only application component that exists is `yelb-appserver`. This is a Sinatra application that basically read and write to a cache server (`redis-server`) as well as a Postgres backend database (`yelb-db`). Redis is used to store the number of page views whereas Postgres is used to persist the votes. Note that the `yelb-db` container image is nothing more than Postgres (10) customized to create the database schema the application relies on.
2020

2121
The picture below shows the architecture of Yelb:
2222

@@ -30,16 +30,18 @@ This is how the UI looks like at this point:
3030

3131
![yelb-ui](yelb-ui.png)
3232

33-
The nature of the app allows people to experiment with the statless `yelb-ui` and `yelb-appserver` components (think scaling out, blue/green depoyments, etc.) as well as experiment with the stateful `redis-server` backend component (think leveraging persistent volumes, etc.).
33+
The nature of the app allows people to experiment with the statless `yelb-ui` and `yelb-appserver` components (think scaling out, blue/green depoyments, etc.) as well as experiment with the stateful `redis-server` and `yelb-db` backend components.
3434

3535
#### How can I use it?
3636

3737
If you intend to contribute, fork or understand anyway how the single components work I suggest you dig into each of them looking at the code (and the various dockerfiles) to learn how they work and how they are packaged. In addition to that you should look into the `deployments` folder how to start the application in development mode and test mode.
3838

39-
If you intend to use Yelb as a generic application with the ultimate goal of learning and playing with container platforms, then you should probably go straight into the `deployments` folder and specifically in the `platformdeployment` folder. This is where all the various configuration files for the various platforms exist (or will exist). This folder will ideally be a continuous work in progress.
39+
If you intend to use Yelb as a generic application with the ultimate goal of learning and playing with multiple platforms (from cloud instances, to containers through potentially serverless), then you should probably go straight into the `deployments` folder and specifically in the `platformdeployment` folder. This is where all the various configuration files for the various platforms exist (or will exist). This folder will ideally be a continuous work in progress.
4040

4141
#### Known issues and limitations
4242

4343
- There is a subtle issue when you browse the app for the first time where the browser console shows errors. This is likely due to problems with variables not initialized properly. This needs further investigation. The app works just fine and there is no evidence of the problem unless you inspect the page and go to the console outputs.
44-
- There is a ton of optimization that could be achieved both in the application code as well as in the packaging constructs (e.g. Dockerfiles). The package in its current form works but it is far from being considered optmized.
45-
- While the intent was to build an application whose layers could scale out (and scale independently) in a classic microservices scenario, very little testing has gone into multi-container deployment scenarios so far. Most of the tests have been done with one (1) container per layer.
44+
- There is a ton of optimization that could be achieved both in the application code as well as in the packaging constructs (e.g. Dockerfiles). The package in its current form works but it is far from being considered optmized.
45+
- Idempotency may be a problem. While I am trying to explicitly declare container tags and modules versions moving forward, there is a chance that if you try to build your own containers from the Dockerfile provided and/or install the project on a cloud instance, the output may be diverging from one setup to another. Generic `apt-get update`, `npm install` `gem install sinatra` instructions may lead to different versions of code and modules being pulled at build and setup times.
46+
- The cache instance is still named `redis-server` (this will be renamed `yelb-cache` in the future for consistency)
47+
- While the intent was to build an application whose layers could scale out (and scale independently) in a classic microservices scenario, very little testing has gone into scale out deployment scenarios so far. Most of the tests have been done with one (1) instance of service per layer.

deployments/localdevelopment/setupdevenv.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11

22
#!/bin/bash
33

4-
# workstation requirements: git, Docker, Ruby (with proper libraries), angular@CLI
4+
# workstation requirements: git, Docker, Ruby (with proper libraries/gems), angular@CLI
55

6-
docker run --name redis -p 6379:6379 -d redis
6+
docker run --name redis -p 6379:6379 -d redis:4.0.2
7+
docker run --name postgres -p 5432:5432 -d mreferre/yelb-db:0.2
78

89
cd ./yelb/yelb-appserver
910
export RACK_ENV=development

deployments/localtest/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ Move to the directory where you want to work and clone the repo:
66

77
```
88
docker network create yelb-network
9-
docker run --name redis-server -p 6379:6379 --network=yelb-network -d redis
10-
docker run --name yelb-appserver --network=yelb-network -d -p 4567:4567 -e RACK_ENV=test mreferre/yelb-appserver
11-
docker run --name yelb-ui --network=yelb-network -d -p 8080:80 -e UI_ENV=test mreferre/yelb-ui
9+
docker run --name redis-server -p 6379:6379 --network=yelb-network -d redis:4.0.2
10+
docker run --name yelb-db -p 5432:5432 --network=yelb-network -d mreferre/yelb-db:0.2
11+
docker run --name yelb-appserver --network=yelb-network -d -p 4567:4567 -e RACK_ENV=test mreferre/yelb-appserver:0.2
12+
docker run --name yelb-ui --network=yelb-network -d -p 8080:80 -e UI_ENV=test mreferre/yelb-ui:0.2
1213
```
1314
You should now be able to see the application running by connecting your browser to: http://localhost:8080
1415

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#use this with `docker-compose up` against a generic Docker end-point (e.g. standalone Docker, VIC)
1+
#use this with `docker-compose up` against a generic Docker end-point (e.g. standalone Docker)
22
version: "2.1"
33
services:
44
yelb-ui:
5-
image: mreferre/yelb-ui
5+
image: mreferre/yelb-ui:0.2
66
depends_on:
77
- yelb-appserver
88
ports:
@@ -11,15 +11,21 @@ services:
1111
- UI_ENV=test # dev | test | prod
1212

1313
yelb-appserver:
14-
image: mreferre/yelb-appserver
14+
image: mreferre/yelb-appserver:0.2
1515
depends_on:
1616
- redis-server
17+
- yelb-db
1718
ports:
1819
- 4567:4567
1920
environment:
2021
- RACK_ENV=test # development | test | production
2122

2223
redis-server:
23-
image: redis
24+
image: redis:4.0.2
2425
ports:
2526
- 6379:6379
27+
28+
yelb-db:
29+
image: mreferre/yelb-db:0.2
30+
ports:
31+
- 5432:5432
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
These configurations had been lightly tested against Docker for Mac (configured as a single node Swarm cluster).
22

3-
These two scripts should work against a simple docker host (which includes support for a VMware VCH or a `Swarm legacy` cluster) as well as a `Swarm mode` cluster.
3+
These two scripts should work against a simple docker host (which includes support for `Swarm legacy` clusters) as well as a `Swarm mode` cluster.
44

55
This is a WIP.
Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# use this with `docker-compose up` against a generic Docker end-point (e.g. standalone Docker, VIC)
1+
# use this with `docker-compose up` against a generic Docker end-point (e.g. standalone Docker)
22
version: "2.1"
33
services:
44
yelb-ui:
5-
image: mreferre/yelb-ui
5+
image: mreferre/yelb-ui:0.2
66
depends_on:
77
- yelb-appserver
88
ports:
@@ -11,25 +11,36 @@ services:
1111
- yelb-network
1212

1313
yelb-appserver:
14-
image: mreferre/yelb-appserver
14+
image: mreferre/yelb-appserver:0.2
1515
depends_on:
1616
- redis-server
17+
- yelb-db
1718
networks:
1819
- yelb-network
1920

2021
redis-server:
21-
image: redis
22+
image: redis:4.0.2
2223
networks:
2324
- yelb-network
2425
# uncomment the following lines if you want to persist redis data across deployments
2526
#volumes:
26-
# - data:/data
27+
# - redisdata:/data
28+
29+
yelb-db:
30+
image: mreferre/yelb-db:0.2
31+
networks:
32+
- yelb-network
33+
# uncomment the following lines if you want to persist postgres data across deployments
34+
#volumes:
35+
# - postgresqldata:/var/lib/postgresql/data
2736

2837
networks:
2938
yelb-network:
30-
driver: bridge # a user defined bridge is required; the default bridge network doesn't support name resolution
39+
driver: bridge # a user defined bridge is required; the default bridge network doesn't support name resolution
3140

32-
# uncomment the following lines if you want to persist redis data across deployments
41+
# uncomment the following lines if you want to persist redis/postgres data across deployments
3342
#volumes:
34-
# data:
35-
# driver: local # you can pick another driver depending on the platform you are deploying onto
43+
# redisdata:
44+
# driver: local # you can pick another driver depending on the platform you are deploying onto
45+
# postgresqldata:
46+
# driver: local # you can pick another driver depending on the platform you are deploying onto

deployments/platformdeployment/Docker/stack-deploy.yaml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
version: "3"
33
services:
44
yelb-ui:
5-
image: mreferre/yelb-ui
5+
image: mreferre/yelb-ui:0.2
66
depends_on:
77
- yelb-appserver
88
ports:
@@ -15,9 +15,10 @@ services:
1515
condition: on-failure
1616

1717
yelb-appserver:
18-
image: mreferre/yelb-appserver
18+
image: mreferre/yelb-appserver:0.2
1919
depends_on:
2020
- redis-server
21+
- yelb-db
2122
networks:
2223
- yelb-network
2324
deploy:
@@ -26,12 +27,24 @@ services:
2627
condition: on-failure
2728

2829
redis-server:
29-
image: redis
30+
image: redis:4.0.2
3031
networks:
3132
- yelb-network
3233
# uncomment the following lines if you want to persist redis data across deployments
3334
#volumes:
34-
# - data:/data
35+
# - redisdata:/data
36+
deploy:
37+
replicas: 1
38+
restart_policy:
39+
condition: on-failure
40+
41+
yelb-db:
42+
image: mreferre/yelb-db:0.2
43+
networks:
44+
- yelb-network
45+
# uncomment the following lines if you want to persist postgres data across deployments
46+
#volumes:
47+
# - postgresqldata:/var/lib/postgresql/data
3548
deploy:
3649
replicas: 1
3750
restart_policy:
@@ -41,7 +54,10 @@ networks:
4154
yelb-network:
4255
driver: overlay # a user defined bridge is required; the default bridge network doesn't support name resolution
4356

44-
# uncomment the following lines if you want to persist redis data across deployments
57+
# uncomment the following lines if you want to persist redis/postgres data across deployments
4558
#volumes:
46-
# data:
47-
# driver: local # you can pick another driver depending on the platform you are deploying onto
59+
# redisdata:
60+
# driver: local # you can pick another driver depending on the platform you are deploying onto
61+
# postgresqldata:
62+
# driver: local # you can pick another driver depending on the platform you are deploying onto
63+

deployments/platformdeployment/Kubernetes/cnawebapp-minikube-hostport.yaml

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,29 @@ metadata:
66
name: redis-server
77
labels:
88
app: redis-server
9-
tier: backend
9+
tier: cache
1010
spec:
1111
type: ClusterIP
1212
ports:
1313
- port: 6379
1414
selector:
1515
app: redis-server
16-
tier: backend
16+
tier: cache
17+
---
18+
apiVersion: v1
19+
kind: Service
20+
metadata:
21+
name: yelb-db
22+
labels:
23+
app: yelb-db
24+
tier: backenddb
25+
spec:
26+
type: ClusterIP
27+
ports:
28+
- port: 5432
29+
selector:
30+
app: yelb-db
31+
tier: backenddb
1732
---
1833
apiVersion: v1
1934
kind: Service
@@ -45,7 +60,7 @@ spec:
4560
spec:
4661
containers:
4762
- name: yelb-ui
48-
image: mreferre/yelb-ui
63+
image: mreferre/yelb-ui:0.2
4964
ports:
5065
- containerPort: 80
5166
hostPort: 32777 # depending on the minikube driver you use you may be able to even use 80. But something above 32000 seems safer
@@ -60,16 +75,34 @@ spec:
6075
metadata:
6176
labels:
6277
app: redis-server
63-
tier: backend
78+
tier: cache
6479
spec:
6580
containers:
6681
- name: redis-server
67-
image: redis
82+
image: redis:4.0.2
6883
ports:
6984
- containerPort: 6379
7085
---
7186
apiVersion: extensions/v1beta1
7287
kind: Deployment
88+
metadata:
89+
name: yelb-db
90+
spec:
91+
replicas: 1
92+
template:
93+
metadata:
94+
labels:
95+
app: yelb-db
96+
tier: backenddb
97+
spec:
98+
containers:
99+
- name: yelb-db
100+
image: mreferre/yelb-db:0.2
101+
ports:
102+
- containerPort: 5432
103+
---
104+
apiVersion: extensions/v1beta1
105+
kind: Deployment
73106
metadata:
74107
name: yelb-appserver
75108
spec:
@@ -82,7 +115,7 @@ spec:
82115
spec:
83116
containers:
84117
- name: yelb-appserver
85-
image: mreferre/yelb-appserver
118+
image: mreferre/yelb-appserver:0.2
86119
ports:
87120
- containerPort: 4567
88121

0 commit comments

Comments
 (0)