This explains how to configure Flask, Celery, RabbitMQ and Redis, together with Docker to build a web service that dynamically uploads the content and loads this content when it is ready to be displayed. Weβll focus mainly on Celery and the services that surround it. Docker is a bit more straightforward.
The finished project structure will be as follows:
βββ Dockerfile
βββ docker-compose.yml
βββ README.md
βββ app
β βββ app.py
β βββ tasks.py
β βββ templates
β βββ download.html
β βββ index.html
βββ scripts
β βββ run_celery.sh
β βββ run_web.sh
βββ requirements.txt
First, we create a folder for our app. For this example, our folder is called app
. Within this folder, create an app.py
file and an empty folder named templates
where our HTML templates will be stored.
For our app, we first include some basic Flask libraries and create an instance of the app:
from io import BytesIO
from flask import Flask, request
from flask import render_template, make_response
APP = Flask(__name__)
We define three routes for Flask to implement: a landing page, a secondary page that embeds and image, and a route for the image itself. Our image route crops an image dynamically. For this example, it crops an image using pillow
, and some delays are also included so that the time taken to create the image is more apparent.
@APP.route(β/β)
def index():
return render_template(βindex.htmlβ)
@APP.route(β/image_pageβ)
def image_page():
job = tasks.get_data_from_strava.delay()
return render_template(βhome.htmlβ)
@APP.route('/result.png')
def result():
'''
Pull our generated .png binary from redis and return it
'''
jobid = request.values.get('jobid')
if jobid:
job = tasks.get_job(jobid)
png_output = job.get()
png_output="../"+png_output
return png_output
else:
return 404
#rabbitmq #celery #flask #docker #redis