About the tools
We will start with a summary of the tools that we will use:
- VS Code: Popular code editor.
- Flask: Small web server that we can set up with little code.
- Gunicorn: A simple WSGI HTTP Server in which we can mount Flask.
- Postman: An easy platform to test our Rest APIs.
- Gitlab: Version control service in the cloud and DevOps integration.
- Heroku: Platform that allows us to upload projects and deploy them online.
What do we need?
- Create your web app with Flask.
- Prepare your project repository with Gitlab.
- Create an account in Heroku.
Configuring our project: Flask and Gunicorn
In this section we gonna prepare our Flask app, the Heroku deploy file and the Gitlab CI configuration.
The Flask project
First, this is my Flask project: a simple Rest API that has a ping and a greeting endpoint.
import os
from dotenv import load_dotenv
from flask import Flask, jsonify
server = Flask(__name__)
@server.route("/api/ping", methods=['GET'])
def api_ping():
return jsonify({"message": "pong"})
@server.route("/api/salute/<string:name>", methods=['GET'])
def api_salute(name: str):
env = os.getenv("ENV")
return jsonify({"message": f"Hi {name}!", "env": env})
if __name__ == "__main__":
load_dotenv()
server.run(host="localhost", port=8000, debug=True)
Note that we are also using environment variables, this is very common when we are working with web projects. I only set a single variable with a cheerful message (we gonna change this in staging and production):
ENV="Hello from Local"
Then I just can simply run the app with python app.py
and then go to Postman to tests the endpoints, nothing strange until now.
Heroku deploy file
Now we need to create a file called Procfile
without extension in the root folder of our project, this is file is gonna be used by Heroku to know how to execute our app.
We gonna write the command to execute our app with Gunicorn, just this simple line:
web: gunicorn 'app:server'
Look how I just set the filename where my flask app is created and the flask instance name. In our example is in the file app.py
and the variable is named as server
, this is why we set app:server
.
The Gitlab CI configuration
Then, we need to prepare the Gitlab CI file to deploy to Heroku. This is the template that we gonna use, name it as .gitlab-ci.yml
.
image: python3:latest
before_script:
- apt-get update -qy
- apt-get install -y ruby-dev
- gem install dpl
stages:
- deploy
staging:
stage: deploy
image: ruby:latest
script:
- dpl --provider=heroku --app=$HEROKU_APP_DEV --api-key=$HEROKU_API_KEY
only:
- dev
production:
stage: deploy
image: ruby:latest
script:
- dpl --provider=heroku --app=$HEROKU_APP_PROD --api-key=$HEROKU_API_KEY
only:
- main
The important configuration here is in the deploy stage where we set that any merge to the branches dev or main will cause a deploy to Heroku.
Branch name | Deploy to |
dev | Staging |
main | Production |
After saving this file, this is how our project directory looks like:
Configuring Heroku
In the Heroku section, we gonna create the project apps, set the environment variables, and get the Heroku API Key to allow the Gitlab CI pipelines to deploy in Heroku.
Creating the projects
We need to go to our account in Heroku and create two new projects: one for staging and the other for production.
Now create the staging one. This is the result:
Look how I named the projects:
Heroku project name | Deploy to |
hhsm-webapp-staging | Staging |
hhsm-webapp | Production |
Configuration of the environment variables
After that, we gonna create a set of the ENV variable in Heroku for each project:
- Enter to each app and in the “Settings” tab.
- Then in the “Config Vars” section press the “Reveal Config Vars” button.
- Now enter the variable name
ENV
and write:Hello from Production
in production app andHello from Staging
in staging app. In a real app this could be a database host, user, password or database name. - Finally, press the “Add” button to save it.
Getting the Heroku API Key
Finally, we need the API Key to allow Gitlab CI to deploy our apps to Heroku.
- For this, we need to go to our “Account settings”.
2. The in the “API Key” section, generate or reveal your current key and copy it.
Once copied we gonna continue in the Gitlab section.
Configuring Gitlab
In this section we gonna protect the dev branch and set the variables for the Gitlab CI configuration.
Protecting the dev branch
First, we need to configure our staging branch as protected to be able to deploy and use variables on it.
For that go to the “Settings” > “Repository” option.
Then to the “Protected branches” section and add the dev
branch to protected with this configuration:
- Branch name:
dev
- Allowed to merge: Mantainers
- Allowed to push: Developers and Mantainers
- Allowed to force push: True
- Code owner approval: False
With this, we protect the dev branch.
Settings the Gitlab CI variables
The next step is to configure our Gitlab project setting the variables in the gitlab-ci.yml
:
HEROKU_API_KEY
: The API Key that we get in the last step.HEROKU_APP_DEV
: The Heroku app name for the staging deploy.HEROKU_APP_PROD
: The Heroku app name for the production deploy.
For this, we need to go to “Settings” > “CI / CD”:
Now we need to create the 3 variables in the “Variables” section with the button “Add variable”:
Adding HEROKU_API_KEY
, remember you copied this in previous steps. Just set the name as seen and paste the value. The checkboxes configuration is okay by default.
Then add the other 2 variables with the names and values, remember how you name them when you create the Heroku apps. In my case was:
HEROKU_APP_DEV: hhsm-webapp-staging
HEROKU_APP_PROD: hhsm-webapp
This is how they look:
With this we finish the Gitlab section, lets continue to the final step.
Deploy and test our project
Pushing your code to Gitlab
Now just push your code to Gitlab, the pipeline will run automatically if you push your branch main or dev.
I pushed the main and dev branches and in the Pipelines section of the Gitlab project, I can see both pipelines passed.
Check Heroku
If you check any app in Heroku, you will see the next 2 steps: “Build succeeded” and “Deployed”.
Now grab the app URL pressing the “Open app” button in the header of Heroku:
Test with Postman
Finally, we need to check our API with Postman.
First the ping endpoint with the staging app:
Finally the salute endpoint with the production app:
Look how the endpoint shows that is the production app with the ENV variable.
Now let’s test the same endpoint but in the staging app:
Final thougths
And this is it, now you know how to easily deploy your Python Flask web apps online with Gitlab and Heroku.
This is the repo with all the discussed files: https://gitlab.com/hhsm95-blog/flask-app-deploy-to-heroku
I hope this helps you and makes your projects a little bit easier to test and share with other devs.
If you feel newbie about Python, check this book for beginners: https://amzn.to/3m0hYlS.
Also, if you need to reinforce your knowledge in Flask you can see this: https://amzn.to/3m7wpor.
Or maybe you’re a Django guy: https://amzn.to/3ifkML6.
Thanks for reading!