Using environment variables in a Flask + Heroku project
Using environment variables is fundamental in a project. This is how
you tell your app if you are running in production
or
locally
for example. This is where you also store more
sensible information like SECRET_KEY
or API credentials.
Storing those directly in your web app code can be easy at first, but it
is not safe when you will push your code in production, so taking good
habits from the beginning is a good idea.
Before jumping in the topic of configuring environment variables, I will first make you set up and deploy a basic app.
Flask
In this project I use Flask. Create a folder for your app and a new virtual environment (check out poetry if you don’t know what it is). Once your virtual environment is running, we need to install a few dependencies first :
# if you use poetry as virtual environment manager
# use the command 'poetry add' instead of 'pip install'
pip install flask gunicorn
Flask is the web server running with python, and Gunicorn is what will basically run our web server on Heroku when we will deploy our app.
Lets first set up a basic app and create a file app.py
in your folder :
import os
from flask import Flask, render_template
= Flask(__name__)
app
@app.route('/')
def index():
= "Hello"
greeting try:
= os.environ['EXCITED']
excited = greeting + "!!!!!"
greeting except:
pass
return render_template("index.html", greeting=greeting)
As you see we will render an index.html
so create that
file too inside a templates
folder and paste this code
inside :
<!doctype html>
<html>
<head>
<title>My App</title>
</head>
<body>
{{ greeting }}</body>
</html>
Before running the web app locally we need to set two variable in your terminal so Flask knows what to do exactly :
export FLASK_ENV=development
export FLASK_APP=app.py
export EXCITED=True
Lets run our app locally with flask run
. As you can see
we are greeted like expected, with all the ‘!!!!’, but I had to export
the variable in my terminal. Every time you close your terminal you need
to do that again. Not very efficient.
Heroku
Now if we want to deploy our app on Heroku we need to do a few things.
-
Create a
Procfile
at the root of your folder. Paste this code inside :web: gunicorn app:app
-
We need to export all the python dependencies in a
requirements.txt
file :pip freeze > requirements.txt # if you use poetry you can do as following poetry export -f requirements.txt > requirements.txt
-
Install Heroku CLI on your machine and then login on your Heroku account (here to register):
# if you are on mac and use homebrew brew tap heroku/brew && brew install heroku # you can also use npm npm install -g heroku
-
Once Heroku is available on your terminal, we can create your Heroku App :
heroku create <name_of_your_app>
Now if you check your Heroku Dashboard in the browser, you’ll see an application with that name. But it doesn’t have our code or anything yet - it’s completely empty. Let’s get our code up there.
-
The next step is initializing git in your repository, and add the Heroku remote in your git repository :
git init heroku git:remote -a <name_of_your_app>
-
Now before pushing our app on Heroku, we need to set that
EXCITED
variable to true. You can do that on the web interface of Heroku, or using the CLI with :heroku config:set EXCITED=True
-
To push our web app to Heroku we can simply do :
git add . git commit -m"deploying app on heroku" git push heroku master
Now if you look at https://name_of_your_app.heroku.com
you should have a nice excited greeting message :
Hello !!!!
Environment Variable
Alright, thank you Mathieu, but how is that suppose to teach us how to manage environment variable ?
Well, now that you are set up properly, let me introduce the
.env
and .flaskenv
files. By convention, the
.flaskenv
is where you store your variables related to your
flask configuration, such as the type of environment, or the files that
contains your flask app. For this example we will write those lines
inside this file :
#.flaskenv file
FLASK_APP=app.py FLASK_ENV=development
Now the .env
file contains the sensible variable
information that your app needs to run. This file stay locally and you
must include it in your .gitignore
to avoid sharing
sensible informations. For the purpose of this tutorial we will just
include one variable :
#.env file
EXCITED=True
Your folder structure should look something like this :
.
├── templates
└── index.html
├── .env
├── .flaskenv
├── .gitignore
├── Procfile
├── app.py └── requirements.txt
Now we have two different use case possible. If you want to use flask to run your app locally you need to install one more dependencies
pip install python-dotenv
# with poetry use
poetry add python-dotenv
You don’t need to do anything else, thanks to this new package, flask will automatically detect your two new files and will load their variables in the app context.
If instead of using flask to run your app locally you prefer to use
heroku local web
then you don’t need to install
python-dotenv
, Heroku will detect the .env
file by itself.
Conclusion
We saw how to implement a behavior that allows us to protect our
sensible information by putting them in external files that wont be
pushed to a public git repository. In the same time our app will work
seamlessly when deployed on Heroku, if you set up the same variables in your .env
files on the config of your Heroku app (with the
web interface or the CLI).
You can find all the code of this tutorial here.
Comments
Comments powered by Disqus