- This is a hello-world containerized Flask app that expects a string in POST payload and responds with a result pretty much like a CLI utility.
- It comes with Grafana requests’ gragh.
- NB! There are some bad design decisions for the sake of simplicity (e.g. putting monitoring and the app itself into a single pod).
- Also, a production-grade app must use ingress instead of NodePort.
- Also, a good nginx configuration must ensure invalid requests can’t even reach the app.
- Also, a nice project would have a CI pipeline to test Dockerfile build, run unit and monitoring testing, and deploy the thing somewhere. Yet, it’s just a dumb string manipulation app.
- The service is deployed at localhost by default.
- Port 80 is served by nginx.
- Grafana is available at
http://127.0.0.1/grafanawith admin:admin login pair. - Grafana provides total request count graph in pystringer dashboard.
### from the project root
$ docker-compose up -d
- Minikube assigns random IPs and ports for external services.
- Minikube instance should be running upon deployment.
- Grafana is available at http://$MINIKUBE_SERVICE_IP:PORT/grafana/login
### start minikibe
$ minikube start
### inject Docker envs to minikube instance
### to enable locally built image discovery
$ eval $(minikube -p minikube docker-env)
### build pystringer image
$ docker build -t pystringer -f ./docker/Dockerfile.app .
### deploy the app
$ kubectl apply -f ./k8s
### wait until the pod is operational
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pystringer-dep-7d65d4b4d6-gbgxn 4/4 Running 0 79s
### expose the service
$ minikube service pystringer-service
### get the URL
$ minikube service --all
😿 service default/kubernetes has no node port
|-----------|--------------------|--------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|--------------------|--------------|---------------------------|
| default | kubernetes | No node port |
| default | pystringer-service | 80 | http://192.168.49.2:31527 |
|-----------|--------------------|--------------|---------------------------|
### run unit testing
$ PYSTRINGER_URL=http://192.168.49.2:31527 python3 app_test.py
- It is quite similar to k8s deployment.
### start minikube
$ minikube start
### export minikube envs
$ eval $(minikube -p minikube docker-env)
### build the Docker image
$ docker build -t pystringer -f ./docker/Dockerfile.app .
### deploy the chart
$ helm install pystringer pystringer-helm
### get the service URL
$ minikube service --all
😿 service default/kubernetes has no node port
|-----------|--------------------|--------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|--------------------|--------------|---------------------------|
| default | kubernetes | No node port |
| default | pystringer-service | 80 | http://192.168.49.2:32427 |
|-----------|--------------------|--------------|---------------------------|
### run unit testing
$ PYSTRINGER_URL=http://192.168.49.2:32427 python3 app_test.py
- By default on docker-compose deployment, nginx frontend listens on 127.0.0.1:80 and forwards requests to uWSGI running in a separate container.
- Make sure you have
curlinstalled.
### get list of valid requests
$ curl http://127.0.0.1
Valid requests: lowercase, uppercase, reverse, randomcase
### convert a string to lowercase
$ curl -d 'LOREM IPSUM DOLOR SIT AMET' http://127.0.0.1/lowercase
lorem ipsum dolor sit ame
### convert a string to uppercase
$ curl -d 'lorem ipsum dolor sit ame' http://127.0.0.1/uppercase
LOREM IPSUM DOLOR SIT AME
### convert a string to randomcase (that's my favorite)
$ curl -d 'lorem ipsum dolor sit ame' http://127.0.0.1/randomcase
loReM ipsuM DOloR SIt AME
### reverse a string
$ curl -d 'lorem ipsum dolor sit ame' http://127.0.0.1/reverse
ema tis rolod muspi merol
- Unit testing is implemented as a simple infinite loop that selects a method randomly on each iteration, generates a random string, and asserts against a known result.
- Also, it’s quite useful to populate metrics with some data.
- You may optionally provide a URL via
PYSTRINGER_URLenivornment variable.
### make sure you have requests module installed
$ python3 app_test.py
randomcase: cfrrxczxrpblfailvgilbaljpcststqfhcjwdvyfb
response: cfrRxCZXrpbLFAiLVGilBALjpCSTSTQFhcjwdVyFB
**************************************************
lowercase: dbrgkrktghz
response: dbrgkrktghz
**************************************************
...