Demo flask application connected to mongodb with kubernetes compliant health probe endpoints.
version: "3.9"
volumes:
prod_data:
services:
flask:
image: flaskapp:0.1.8-prod
build:
context: ./
dockerfile: Dockerfile
args:
build_date: '2021-04-25'
version: 0.1.8-prod
ports: [5000:5000]
volumes: ["./log:/var/log"]
environment:
MONGO_URI: mongodb://root:rootpassword@mongo/ # valid rfc connection string
GUNICORN_CMD_ARGS: --capture-output # see docs for all options
LOG_LEVEL: error # debug|info|warning|error|critical
LOG_FORMAT: json # json|text
FILTER_PROBES: '1' # 0|1 - don't log requests to healthcheck endpoints with access logger
mongo:
image: mongo:latest
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: rootpassword
volumes: [prod_data:/data/db]
The below command will start the flask application and a mongodb in docker container.
docker-compose up
Once the container are running, the flask documentation can be downloaded as pdf
curl localhost:5000/pdf > flask.pdf
There is also an endpoint to accept message posts.
$ curl -i -H "Content-Type: application/json" -X POST -d '{"message":"hello, flask"}' http://localhost:5000/msg
HTTP/1.1 201 CREATED
Server: gunicorn
Date: Sat, 24 Apr 2021 15:08:22 GMT
Connection: keep-alive
Content-Type: application/json
Content-Length: 34
{"id":"60843466092d7c719ec5063b"}
A list of all messages can be retrieved on the msg endpoint.
$ curl localhost:5000/msg
[{"_id": {"$oid": "60843466092d7c719ec5063b"}, "message": "hello, flask"}]
As long as the app is running it will serve a 200 response on the /alive
endpoint.
$ curl -i localhost:5000/alive
HTTP/1.1 200 OK
Server: gunicorn
Date: Mon, 26 Apr 2021 01:33:25 GMT
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Content-Length: 0
As long as the database connection is working the app will return a 200 response on /ready
.
$ curl -Is localhost:5000/ready | head -n 1
HTTP/1.0 200 OK
The behavior can be be tested by shutting down the database container. Once the database is down, the application with return a status 503 response.
$ docker-compose stop mongo
$ curl -Is localhost:5000/ready | head -n 1
HTTP/1.0 503 SERVICE UNAVAILABLE
Once the database is started up again the app will return again a 200.
$ docker-compose start mongo
$ curl -Is localhost:5000/ready | head -n 1
HTTP/1.0 200 OK
The format of the output is by default json
to play nicely with modern tools. However it can be set to text
via the environment variable LOG_FORMAT
. Likewise the log level can be set via LOG_LEVEL
.
LOG_LEVEL: info # debug|info|warning|error|critical
LOG_FORMAT: json # json|text
The application logs by default into to stdout and stderr. The output can also be directed to log files if needed. For this the gunicorns command line args or flags can be used.
volumes: ["./log:/var/log"]
environment: ["GUNICORN_CMD_ARGS=--capture-output"]
The connection string is set via
MONGO_URI: mongodb://user:password@server/
The GUNICORN_CMD_ARGS
variable can be used as per documentation. This can be useful do do some tweaking ad hoc.
GUNICORN_CMD_ARGS: "--workers=6 --threads=4"
The project is using pipenv
to manage dependencies. It can be useful to set up the virtual environment locally.
pipenv shell
pipenv install --dev
Install the pre-commit hook
pre-commit install
Flake8 has been configured to accept a maximum line length of 119. When using VS Code, the following settings can be used in order to have alignment with the pre commit hook.
{
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.formatting.provider": "black"
}
A test environment with hot reload can be started, it will mount the app directory so code changes are picked up and the workers are restarted.
docker-compose -p dev -f dev-compose.yml up
For testing a compose file exists at the root directory. It is configured to connect to a silent test database.
The following command will start the app and a test database container and run the test suit. Afterwards the db container is shut down.
docker-compose -p test -f test-compose.yml up && \
docker-compose -p test -f test-compose.yml down
A nginx-compose exists that creates an additional nginx container to reverse proxy the requests to gunicorn over unix sockets in a shared volume.
This is because gunicorn inst a fully fletched webserver, is is recommend to use a reverse proxy. Nginx plays well with gunicorn.
docker-compose -p proxy -f nginx-compose.yml up --build
For convenience the commands are available via make.
make
make proxy
make test
make dev