Heroku is a fantastic service that lets you get your app on the web quickly, for free (with the base model).
If you followed my previous post Django, A Framework for Python Web Apps, then you already have most of the tools you need to publish your work on the web for demoing and testing purposes. The final step is hosting your project on Heroku.
Publishing an update to Heroku is as easy as a git remote push (in fact, that’s all there is to it!) Heroku then recognizes the language you’re using and automatically downloads your dependencies, applies your static content, and builds your website from your repository! There are some limitations surrounding what Heroku refers to as dynos, but the important thing is that you’ll be able to get your project hosted with no startup cost, which is useful for testing, sharing your progress, and even using the finished app. I’ve been hosting and USING my recipes, notes, and chores apps for 6+ months and it hasn’t cost me a single cent.
10 Steps to Hosted!
- Step 1: Pull Your Remote GitHub Repository
- Step 2: Install PostgreSQL and Python-Dev
- Step 3: Set Up and Activate Your Virtual Environment
- Step 4: Install Heroku to your Virtual Environment
- Step 5: Create a Requirements File
- Step 6: Add Packages to the Requirements File
- Step 7: Sign Up for Heroku
- Step 8: Configure Your Project for Heroku
- Step 9: Add to Git and Commit
- Step 10: Apply the Migrations
- Step 11: I Guess It Goes to Eleven
Step 1: Pull Your Remote GitHub Repository
First, let’s pull our repository from GitHub, just so that we can keep it in sync with what we’ll be pushing to Heroku. If you’ve made changes of your own, you’ll want to first move (
mv mysite newname) or delete (
rm -rf mysite) your existing mysite folder. Of course, feel free to use your own project, though you may need to tweak the setup slightly to get Heroku to build it out properly.
~ > mkdir ~/mysite ~ > cd ~/mysite ~/mysite > git init ~/mysite > git remote add origin https://github.com/HelloWorldForBeginners/DjangoHelloWorldDemo.git ~/mysite > git pull origin master ls -a
We should see all our files from the GitHub repository, and the git log should have two commits.
Step 2: Install PostgreSQL and Python-Dev
Django projects on Heroku use PostgreSQL by default, so we’ll need to install PostgreSQL on our machine. The linrary libpq-dev provides the client-side requirements for a PostgreSQL application. This is not a Python specific library, and has to be installed with
apt-get rather than
We’ll also need the python-dev library in order to run our database adapter.
~/mysite > sudo apt-get install libpq-dev ~/mysite > sudo apt-get install python-dev
Step 3: Set Up and Activate Your Virtual Environment
If you haven’t already, you’ll want to create a virtual environment for your project. Otherwise, when we install Heroku, it will install in the base Python environment.
The first command will create the virtual environment, and the second will activate it. Once activated, (venv) will appear at the start of each command entry line in your terminal window.
NOTE: be sure to add venv/ to your .gitignore to avoid adding it to your repository.
~/mysite > virtualenv venv ~/mysite > source venv/bin/activate
If you need to disable the virtual environment:
(venv) ~/mysite > deactivate
Step 4: Install Heroku to your Virtual Environment
(venv) ~/mysite > pip install heroku
Step 5: Create a Requirements File
A requirements file captures all of the package requirements for your particular project. It also expedites the package install process by allowing you to install all project package dependencies with a single command, rather than one line at a time. This file can be stored anywhere within your project directory; I prefer to keep it at the root.
First, create the requirements.txt file by using the following command. This command will capture all current dependencies of your project and store them in a file.
(venv) ~/mysite > pip freeze > requirements.txt
Step 6: Add Packages to the Requirements File
Next, add the following packages to your requirements file. This method is only really recommended when you want to install a particular package version. Alternately, you can install your packages using
pip install, then save the entries into requirements.txt by using the
pip freeze command mentioned above.
- Django – Python web framework
- psycopg2 – PostgreSQL database adapter
- gunicorn – Python WSGI HTTP server for UNIX
(venv) ~/mysite > echo "Django==1.9.2" >> requirements.txt (venv) ~/mysite > echo "psycopg2==2.6" >> requirements.txt (venv) ~/mysite > echo "whitenoise==1.0.6" >> requirements.txt (venv) ~/mysite > echo "gunicorn==19.2.1" >> requirements.txt
Step 7: Sign Up for Heroku
Now you’ll need to sign up for Heroku. Write down your password so you can connect your machine’s instance to your account.
Once you’ve signed up, install the Heroku toolbelt.
(venv) ~/mysite > wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh
Now we can login to Heroku through the terminal and create our Heroku app! On the first login, the toolbelt, dependencies, and core plugins will all get set up for you (this may take a few minutes). Once this is done, you’ll be prompted for your email and password.
(venv) ~/mysite > heroku login
After you’ve logged in, you can go ahead and create your project on your Heroku account.
(venv) ~/mysite > heroku create mysite-demo
Our project has been created! Note the web and git urls provided in the output. Very handy! Better yet, Heroku can open your web page in a browser. Just type
heroku open in your terminal.
Now let’s navigate to our Heroku dashboard to set up our database and retrieve the connection details; we’ll need these to set up our app.
From the Dashboard:
- Click your project name.
- On the next page, under the Resources header, type postgreSQL into the search box.
- Choose ‘Heroku Postgres’ and select the ‘Hobby Dev – Free’ option.
- Now you should have a PostgreSQL database provisioned, so click the new link named ‘Heroku Postgres’.
- On the next page, click the database name to view the connection details.
- You will need the password in order to connect, so click show.
- Keep this page open for use in the next section.
Step 8: Configure Your Project for Heroku
Add the Procfile
This file goes in the root of your project, with no extension; it tells Heroku what process to run. Notice that we included the project name after gunicorn. This is so Heroku knows where to find the wsgi.py file.
(venv) ~/mysite > echo "web: gunicorn mysite.wsgi --log-file -" >> Procfile
Update wsgi.py With Whitenoise
Update the wsgi file to include Whitenoise, which tells Heroku what static files to gather. We’ll talk more about static files in the next post.
(venv) ~/mysite > cd mysite (venv) ~/mysite/mysite > pico wsgi.py
Add the following line to the imports:
from whitenoise.django import DjangoWhiteNoise
Add the following line after the existing ‘application = …’ line:
application = DjangoWhiteNoise(application)
Update settings.py With Database Settings
Update DB info in settings.py with your Heroku Postgres information. I used a text editor here instead of pico, just for easy information transfer. The settings.py file is located in your projects PROJECT root folder (named the same as the project by default). In our case, that’s the ~/mysite/mysite directory.
Replace the DATABASES =  section with your PostgreSQL database credentials. If you use the credentials from my screen shot, strange things might happen, so it’s probably best to use your own!
NOTE: Heroku Postgres’ Database field maps to the NAME field in the Django settings.py file.
Step 9: Add to Git and Commit
We’re so close I can taste it. Mmmm… Cheetos dust.
When we created our Heroku project, the toolbelt automatically added a remote for us, which saves us a step. Now, we just need to navigate to the project root, commit, and push the project!
First, though, I’m going to branch my GitHub project to preserve the files as they were before the Heroku setup.
(venv) ~/mysite > git checkout -b heroku (venv) ~/mysite > git add --all (venv) ~/mysite > git commit -m 'branching for heroku configuration' (venv) ~/mysite > git push origin heroku (venv) ~/mysite > git push heroku master
Issues Encountered During Heroku Build
I ran into two issues regarding the Heroku build.
The first issue involved the requirements.txt file. In my earlier post Basic Git, while demoing .gitignore, I had added *.txt to show how .txt files would get ignored. This is fine, except Heroku needs requirements.txt to build a Python program! So when I attempted to push without the requirements.txt file in the commit, Heroku rejected the push. After editing .gitignore to remove the *.txt criteria, then performing a
git add --all,
git commit --amend,
git push heroku master, Heroku was able to build the app successfully.
The second issue involved my branch. Since the requirements.txt file is currently only on the heroku branch of my git, and Heroku only cares about the master branch, it gets ignored. And as we discovered from the first issue, that file is needed for Heroku to build a Python app. To get around this, we alter the push command slightly, to push our local heroku branch to Heroku’s master branch. I ended up merging the heroku and master branches anyway. It turns out that with all the testing I was doing with the
reset commands, I ended up pushing to GitHub without
view.py hello world configurations! I did warn myself that could happen, so it serves me right.
(venv) ~/mysite > git push heroku heroku:master
Step 10: Apply the Migrations
You may recall from More Django Hello World! that we created the database using the migrate command. While it may seem intuitive to run this same command to migrate to our Heroku PostgreSQL database, it turns out that the migrations can’t be properly applied from a remote connection. Certain elements, such as new fields in your model, cannot be applied locally. Attempting to do so will result in a remote database that doesn’t match the models.py file. I learned this the hard way. At one point I had to dump my data into .csv files, completely recreate the database, then re-upload my data in order to get my local version in sync with what was in my Heroku instance.
Fortunately, I discovered that Heroku provides us with a way to run the Django command to migrate to a database from inside the Heroku environment. We can invoke this command on the Heroku server from our terminal window by prefixing it with
heroku run. This tells Heroku to start up an instance on their server and run the command. There’s one more piece, and that’s the app name, which is how Heroku knows what migrations to apply to which app if you have multiple apps. Since we only have one, we don’t have to tell it which app to apply the migrations to.
(venv) ~/mysite > heroku run python manage.py migrate --app mysite-heroku-demo
Step 11: I Guess It Goes to Eleven
Congratulations! You can now view your app on the web! Simply type
heroku open in your terminal, and a browser will open, pointing you to the root of your project.
But what’s this?! Page not found! Well, that’s because we don’t have a base project URL set up yet. All we set up previously was the /myapp URL. You can also see that the admin URL is available, which Django set up for us by default when we created the project.
Go ahead and tack
/myapp on the end of the URL in your browser bar.
Success! Our web page is on the internet!