Easily deploy your Python Flask web apps online with Gitlab and Heroku

Easily deploy your Python Flask web apps online with Gitlab and Heroku

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?

  1. Create your web app with Flask.
  2. Prepare your project repository with Gitlab.
  3. 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__":
    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

  - apt-get update -qy
  - apt-get install -y ruby-dev
  - gem install dpl

  - deploy

  stage: deploy
  image: ruby:latest
    - dpl --provider=heroku --app=$HEROKU_APP_DEV --api-key=$HEROKU_API_KEY
    - dev

  stage: deploy
  image: ruby:latest
    - dpl --provider=heroku --app=$HEROKU_APP_PROD --api-key=$HEROKU_API_KEY
    - 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 nameDeploy to
Relation between branch names and deploys

After saving this file, this is how our project directory looks like:

Project directory structure
Project directory structure

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.

Create Heroku app
Create Heroku app

Now create the staging one. This is the result:

Created our staging and production apps in Heroku
Created our staging and production apps in Heroku

Look how I named the projects:

Heroku project nameDeploy to
Relation between Heroku app names and deploys

Configuration of the environment variables

After that, we gonna create a set of the ENV variable in Heroku for each project:

  1. Enter to each app and in the “Settings” tab.
  2. Then in the “Config Vars” section press the “Reveal Config Vars” button.
  3. Now enter the variable name ENV and write: Hello from Production in production app and Hello from Staging in staging app. In a real app this could be a database host, user, password or database name.
  4. Finally, press the “Add” button to save it.
Creation ENV variable in the Production app

Getting the Heroku API Key

Finally, we need the API Key to allow Gitlab CI to deploy our apps to Heroku.

  1. For this, we need to go to our “Account settings”.
Profile pop up

2. The in the “API Key” section, generate or reveal your current key and copy it.

API Key section

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.

Gitlab project: Settings > Repository
Gitlab project: Settings > Repository

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
Gitlab project: Protected Branches

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”:

Gitlab project: "Settings" > "CI / CD"
Gitlab project: “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:

Gitlab project: CI/CD > Variables
Gitlab project: CI/CD > Variables

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.

Gitlab project: Pipelines
Gitlab project: Pipelines

Check Heroku

If you check any app in Heroku, you will see the next 2 steps: “Build succeeded” and “Deployed”.

Heroku deployed app
Heroku deployed app

Now grab the app URL pressing the “Open app” button in the header of Heroku:

Heroku open app to grab the URL
Heroku open app to grab the URL

Test with Postman

Finally, we need to check our API with Postman.

First the ping endpoint with the staging app:

Postman testing ping endpoint in staging
Postman testing ping endpoint in staging

Finally the salute endpoint with the production app:

Postman testing salute endpoint in production
Postman testing salute endpoint in production

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:

Postman testing salute endpoint in staging

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!

5 2 votes
Article Rating
Notify of
Inline Feedbacks
View all comments

Pin It on Pinterest

Would love your thoughts, please comment.x