Introduction

Heroku and Convox are both Platforms-as-a-Service designed around The Twelve-Factor App methodologies.

Convox is open-source and built entirely on AWS cloud services. It enables you to deploy your apps to your own AWS account for maximum control. Depending on your application and engineering team, migrating an app to Convox could unlock security, reliability, performance, cost and/or operational improvements.

Many parts of the Heroku platform map directly to Convox:

Heroku Convox
Codebase Git Repo Git Repo
Config
$ heroku config
$ convox env
Build / Release / Run
$ git push heroku master
$ heroku releases
$ convox deploy
$ convox releases
Processes
$ heroku ps
$ convox ps
Concurrency
$ heroku scale
$ convox scale
Databases
$ heroku addons
$ convox resources
Logs
$ heroku logs
$ convox logs
Admin Processes
$ heroku run
$ convox run
$ convox exec

Other parts are similar, but represent more significant changes to your apps:

Heroku Convox
Manifest
Procfile
docker-compose.yml
Ports
Port Assignment
$PORT environment variable
Port Mapping
ports:
  - 80:8000
Development
$ heroku local
Homebrew
$ convox start
Docker
Production
Cedar Stack Image
PaaS
Docker Base Image
IaaS / AWS

This guide explains the differences of the platforms, and walks you through the steps required to migrate an app.

Prerequisites

Let’s start with a simple Python and Postgres Heroku app. The codebase is in a GitHub repo.

First, let’s create an empty Convox app:

convox apps create
Creating app python-getting-started... CREATING

If you don’t have Convox set up in your AWS account, refer to the Getting Started doc.

Convox uses Heroku’s buildpacks to build images for apps. The convox init command will generate a Dockerfile to describe how to build your app with the appropriate buildpack.

To get started, run:

convox init
Updating convox/init... OK
Initializing a python app
Building app metadata. This could take a while... OK
Writing docker-compose.yml... OK
Writing Dockerfile... OK
Writing .dockerignore... OK

Manifest

Heroku Convox
Heroku uses a Procfile to define process types and commands. Convox uses a docker-compose.yml file to define service types and commands.

The previous convox init command generated a docker-compose.yml file for our Convox app. Every process type and command in Procfile is added as a service and command to docker-compose.yml.

version: "2"
services:
  database:
    image: convox/postgres
    ports:
    - 5432/tcp
    volumes:
    - /var/lib/postgresql/data
  web:
    build:
      context: .
    command: gunicorn gettingstarted.wsgi --log-file -
    environment:
    - PORT=4001
    labels:
      convox.port.443.protocol: tls
    links:
    - database
    ports:
    - 80:4001/tcp
    - 443:4001/tcp

Deploying

Now our app can be deployed to Convox:

convox deploy
$ convox deploy
Deploying python-getting-started
Creating tarball... OK
Uploading: 9.56 KB / 9.39 KB [===========================] 101.84 % 0s
Starting build... OK
running: docker build -f /tmp/407003531/Dockerfile -t python-getting-started/web /tmp/407003531
Sending build context to Docker daemon 46.08 kB
Step 1 : FROM heroku/cedar
...
Successfully built d9c7f075f169

running: docker tag 
running: docker push 

web.BXMCXIIFZSQ: digest: sha256:62815bd42414f508c7ce326a42dbc7df484beaf175ee5581ef7c0fda36dad21a size: 1994
Release: RRYXNKQRAPD
Promoting RRYXNKQRAPD... UPDATING

convox apps info
$ convox apps info python-getting-started
Name       python-getting-started
Status     running
Release    RRYXNKQRAPD
Processes  database web
Endpoints  internal-python-getting-started-AT3UMZ4-i-500316325.us-east-1.elb.amazonaws.com:5432 (database)
           python-getting-started-w-IC7MLNI-1004687141.us-east-1.elb.amazonaws.com:80 (web)
           python-getting-started-w-IC7MLNI-1004687141.us-east-1.elb.amazonaws.com:443 (web)

Sure enough, our app is available at the endpoint.

Databases

Heroku Convox
Heroku uses addons to provision database services, and sets app config with service connection information. Convox uses resources to provision database services, and sets app environment with service connection information.

The previous step deployed a database container. A containerized database is good for development and verification purposes, but in production we’ll want a “real” hosted database. There are two strategies.

Reuse Heroku Addons

Both Heroku and Convox run in the AWS cloud. As long as the Heroku addons and Convox app are in the same region, access between them is fast. So the simplest strategy is to connect the Convox app to the Heroku addons by copying over the config.

# copy Heroku config to Convox app environment

heroku config -s | convox env set
Updating environment... OK
To deploy these changes run `convox releases promote RWGFPGSELVA`

convox releases promote RWGFPGSELVA
Promoting RWGFPGSELVA... OK

# verify the Convox environment, database connection and data

convox run web python manage.py migrate
Running migrations:
  No migrations to apply.

Migrate Data

The other strategy is to create new databases and migrate data. This has the security advantage of moving your database and data into a VPC that is not acessable to anything but your Convox app.

To do this, we will backup the Heroku database, and restore it into a new, private Postgres database.

# create the Convox resource and open a local proxy

convox resources create postgres
Creating postgres-2098 (postgres)... CREATING

convox resources proxy postgres-2098
proxying 127.0.0.1:5432 to dev-east-postgres-2098.cyzckls48pd3.us-east-1.rds.amazonaws.com:5432

# stop writing data and capture a backup

heroku maintenance:on

heroku pg:backups:capture
Backing up DATABASE to b001... done

heroku pg:backups:download
Getting backup from ⬢ pure-basin-53177... done, #1
Downloading latest.dump...

# restore the Convox database from the backup

pg_restore -Ov -d app -h localhost -n public -U postgres latest.dump
pg_restore: connecting to database for restore
Password: 
pg_restore: creating TABLE "public.auth_group"
pg_restore: creating SEQUENCE "public.auth_group_id_seq"
...

Scale Down Database Containers

Now that we’ve got a real database set up, we’ll want to scale down the database container so that we’re not running unnecessary resources. Scaling the container to a count of -1 will also deprovision its load balancer, saving us money on our AWS bill.

convox scale database --count=1

Next Steps

Our first deploy to Convox is just the beginning. From here you can explore: