Write a post

How to Run Python and Ruby on Heroku with Multiple Buildpacks

Published Nov 23, 2016Last updated Jan 18, 2017
How to Run Python and Ruby on Heroku with Multiple Buildpacks

One of my mentees here in codementor.io encountered a problem while running Python and Ruby together on Heroku. That session inspired me to write this tutorial—how to run more than one environment on Heroku.

PROBLEM

The project was working in Cloud9 without any problems. However, after deploying to Heroku, the log was displaying error messages about Python problems. Steve had written a scraper in Python, and it was not working. Steve, my mentee, had created an old test environment on Cloud9 for me to work on his problem.

SOLUTION

This solution uses this guideline from Heroku.

I solved the problem by using Heroku multi-buildpacks for Python and Ruby.

Heroku multi-buildpacks

Buildpacks are responsible for configuring your application. Heroku explains buildpacks in its documentation like this: "Buildpacks are composed of a set of scripts and depending on the programming language, the scripts will retrieve the dependencies, and output generated assets or compiled code, and more. This output is assembled into a slug by the slug compiler."

There are many Buildpacks (many can be seen here and here). There are distinct buildpacks for Ruby and Python.

So, If someone wants to deploy Ruby and Python together on Heroku, he needs to use “multiple buildpacks". So, Heroku would use different buildpacks to run your application. Each buildpack creates a distinct environment.

Running apps with Procfile

Steve’s application needs to run on Puma Server (the default web server of Ruby on Rails). So, I needed to create a Procfile. Procfile runs commands automatically after the deployment. Procfiles are responsible for running shellcode on Heroku after deployment. For example, you can start web servers and long-running tasks. See more from here.

So, I created a Procfile file like this on his project's root:

# Procfile
web: bundle exec rails server -p $PORT
worker: python scraper.py

In multiple buildpacks, the order of the buildpacks is critical.

I needed to add Ruby buildpack as the last one because Steve would be running a Puma web server for Ruby. If I had not done it like that, Steve would not be able to run his Ruby server on Heroku. So, I added Python buildpack first and then added Ruby buildpack later. Together, they become "the mighty multiple buildpack," ready to use on Heroku.

# command line commands
heroku buildpacks:clear  # remove all of the buildpacks first
heroku buildpacks:add heroku/python  # add the python buildpack first
heroku buildpacks:add heroku/ruby    # add the ruby buildpack second

heroku buildpacks  # to see what I have done
# === golden-ratio-1618 Buildpack
# 1. heroku/python
# 2. heroku/ruby

Internals of a Buildpack

To know more about the internals of a Buildpack, you can review the Github source of a Buildpack, for example, Ruby. bin/detect file is essential. You can see the source code of this file to see what is needed for Heroku to deploy your app. For example, for Ruby, you need to create a Gemfile in the root directory of your app, or it will fail.

Required packages were missing

However, after adding all of the buildpacks, the project was not functioning on Heroku, yet. That was because of Python requirements.txt file. The file is responsible for adding the required Python packages to your app to be installed on Heroku automatically after each deployment (like Gemfile in Ruby). Every time you deploy, Heroku launches a new instance and initializes it by running those files. They are the required files for the environments, like Python and Ruby.

I also needed to verify the behavior in the local, so I ran pip install -r requirements.txt as a command to install the required packages to the local.

Moreover, I tested the setup with: heroku local command. See more about it here.

I put the required packages by looking to Python scraper’s header code. One of them was lxml. I found its latest version number by looking at its github page (to the tags).

So, we created a requirements.txt file like this:

# requirements.txt file
lxml==3.6.4

So, after delivering the training session, Steve responded like this:

The reaction of Steve after I solved his problem

Conclusion

With this article, my aim was that trying to show how I handled a mentee's request and let you know about how to run multiple-buildpacks on Heroku. Of course, there are many details that I skipped over. Maybe, those can be the next article's topics. Similarly, you can also read more tutorials about Heroku, like: how to parse dashboard Heroku or how to get push notifications when your Heroku app is deployed. See you next time.

Discover and read more posts from thubInanc Gumus
get started
Enjoy this post?

Leave a like and comment for thubInanc

1
1
Spark & Python: Working with RDDs (II)
Linking Docker Containers
Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy