Skip to main content

HEROKU

Introduction#

Heroku is a container-based cloud Platform as a Service (PaaS). Developers use Heroku to deploy, manage, and scale modern applications. It is elegant, flexible, and easy to use, offering developers the simplest path to getting their applications to market. Heroku is fully managed, giving developers the freedom to focus on their core product without the distraction of maintaining servers, hardware, or infrastructure. The Heroku experience provides services, tools, workflows, and polyglot support—all designed to enhance developer productivity. Heroku officially supports Python, Node.js, PHP, Java, Ruby, Go, Scala and Clojure languages. In addition to these languages, any language that runs on Linux with Heroku via a third-party buildpack can be used.

Getting started#

  • Pricing : Flexible pricing options, from personal projects to enterprise applications, and everything in between.

  • Create an account

  • Install the Heroku CLI

    • On macOS : $ brew tap heroku/brew && brew install heroku
    • On ubuntu : $ sudo snap install --classic heroku
    • On Windows : Download the appropriate installer

    To get the installed version : $ heroku --version

    All the heroku CLI commands can be found here.

  • Uninstall the heroku CLI

    • On macOS : $ brew uninstall heroku && rm -rf ~/.local/share/heroku ~/Library/Caches/heroku
    • On ubuntu : $ sudo apt-get remove heroku heroku-toolbelt && rm /etc/apt/sources.list.d/heroku.list
    • On Windows : Start > Control Panel > Programs > Programs and Features Select Heroku CLI, and then click Uninstall
  • Login : $ heroku login to be redirect to the browser or $ heroku login -i to be promted to enter the login credentials

  • Create an application with a random name $ heroku create or specify a custom name $ heroku create <app_name>

  • Open an application : $ heroku open -a <app_name>

  • Running bash : $ heroku run bash -a <app_name>

  • Accessing the heroku postgres database : heroku pg:psql <postgres_addon_name> -a <app_name>

  • Troubleshooting : Put HEROKU_DEBUG=1 before the command to show debugging informations

  • Config vars : It is highly recommended to use environment variables especially in production environment. So, to set a config var $ heroku config:set <env_var_name>=<value> -a <app_name> and to remove it $ heroku config:unset <env_var_name> -a <app_name>

  • Runtime : Heroku runs applications inside dynos — smart containers on a reliable, fully managed runtime environment where the system and language stacks are continually monitored, patched, and upgraded by the Heroku team.

  • Github integration : The seamless GitHub integration means every pull request spins up a disposable Review App for testing, and any repository can be set up to auto-deploy with every GitHub push to a choosen branch (i.e master).

  • Continuous delivery : Heroku Flow uses Heroku Pipelines, Review Apps and GitHub Integration to make building, iterating, staging, and shipping apps easy, visual, and efficient.

  • Application metrics and analytics : Always know what’s going on with the applications thanks to built-in monitoring of throughput, response times, memory, CPU load, and errors.

  • Security and compliance : Heroku regularly performs audits and maintains PCI, HIPAA, ISO, and SOC compliance.

  • Heroku ChatOps : Heroku ChatOps brings Heroku’s popular Pipelines deployment workflow to Slack. With Heroku ChatOps you can deploy and promote code, and get CI test and pull request statuses directly within Slack and more.

  • Code and data rollback : Heroku’s build system and Postgres service give the possibility to roll back the code or the database to a previous state in an instant.

  • Display recent logs : $ heroku logs -a <app_name> to fetch application’s most recent logs or $ heroku logs --tail -a <app_name> to display recent logs and leave the session open for real-time logs to stream in.

  • Maintenance mode : Enabling by $ heroku maintenance:on -a <app_name> and when maintenance actions are completed $ heroku maintenance:off -a <app_name>.

  • Add-ons : Extend, enhance, and manage applications with pre-integrated services. Here are the most used ones :

    • Heroku Postgres : Reliable and secure PostgreSQL as a service with easy setup, encryption at rest, simple scaling, database forking, continuous protection, and more.
    • cloudAMQP : Automates every part of the setup, running and scaling of RabbitMQ clusters.
    • SendGrid : Offers the industry’s most advanced deliverability tools and expertise to make sure the email gets delivered. It’s easy to integrate and highly scalable email infrastructure with powerful and customizable APIs.
    • Sentry : Errors and exceptions tracking that helps to monitor and fix crashes in real time by the integration with many services like Github, Slack, Jira and more.
    • Elasticsearch : Open source, distributed, RESTful search engine, usable by any language that speaks JSON and HTTP.
    • Moesif API Analytics : Leverage user-centric API analytics to drive adoption, usage, and retention.
    • Deploy Hooks : Send a message to specified services (email, campfire, basecamp, IRC, or a custom HTTP end-point) whenever changes deployed. To provision an add-on $ heroku addons:create <addon_name> -a <app_name> or $ heroku addons:remove <addon_name> -a <app_name> to remove it. More add-ons are listed here.

Deployment#

  • Procfile : it is a simple text file without a file extension. It must live in the application’s root directory. It specifies the commands that are executed by the application on startup. It can declare a variety of process types, including:

    • The application’s web server
    • Multiple types of worker processes
    • A singleton process, such as a clock
    • Tasks to run before a new release is deployed

    Example for a web application:

    web: gunicorn mysite.wsgi --log-file - release: python manage.py migrate --no-input worker: celery -A config worker -l info

1. Deploying with Git#

  • Install Git

  • Track the application in Git

    $ cd repo_name $ git init $ git add . $ git commit -m "Commit message"

  • Create a Heroku remote

    • For a new Heroku application

      $ heroku create <app_name>
    • For an existing Heroku application

      $ heroku git:remote -a <app_name>
  • Deploy the code

    • From master branch

      $ git push heroku master
    • From a branch besides master

      $ git push heroku <branch_name>:master

2. Deploying with Docker#

  • Using Container Registry

    • Login to the registry

      $ heroku container:login -a <app_name>
    • Build & push the image

      $ heroku container:push web -a <app_name>
    • Release the pushed image

      $ heroku container:release web -a <app_name>
  • By building docker images with heroku.yml file

Here’s an example that illustrates using a heroku.yml manifest to build Docker images:

setup:  addons:    - plan: heroku-postgresql      as: DATABASE    - plan: cloudamqp      as: BROKER    - plan: sentry      as: SENTRYbuild:  docker:    web: Dockerfilerelease:  command:    - python manage.py migrate  image: webrun:  web:    command:      - python manage.py collectstatic --no-input -v 0 && /bin/bash heroku-exec.sh \      && uwsgi --http :$PORT --enable-threads --http-keepalive --mimefile /etc/mime.types \      --processes 4 --wsgi-file config/wsgi.py --check-static /public_assets \      --static-map /static=/public_assets --static-map /favicon.ico=/public_assets/favicon.ico \      --logto /dev/stdout --logto2 /dev/stderr    image: web  worker:    command:      - bash heroku-exec.sh && celery -A config worker -l info    image: web

The heroku-exec.sh script

`[ -z "$SSH_CLIENT" ] && source <(curl --fail --retry 3 -sSL "$HEROKU_EXEC_URL")`

Is used by Heroku to create a SSH tunnel to the docker container via Heroku CLI.

Heroku dynos expose a dynamic port for the application to bind to. This value is exposed in the \$PORT environment variable.

When heroku.yml is used, the Procfile is not required.

3. Deployment integrations#

  • Github
  • Terraform
  • Heroku to Deploy button

Heroku Exec (SSH Tunneling)#

According to Heroku documentation Heroku Exec is a feature for creating secure TCP and SSH tunnels into a dyno. It allows for SSH sessions, port forwarding, remote debugging, and inspection with popular Java diagnostic tools.

SSH sessions#

It can be enabled by running this command :

$ heroku ps:exec -a <app_name>

Or optionally by specifying the dyno type (i.e web.1) :

$ heroku ps:exec --dyno=<dyno_type> -a <app_name>

Also, it's possible to check the status of Exec connection :

$ heroku ps:exec --status -a <app_name>

Port forwarding#

$ heroku ps:forward 9000 --dyno=<dyno_type> -a <app_name>

This command will forward traffic on the local port (9000) to the port (9000) inside the specified dyno. Then the browser can be connected to localhost:9000, and the requests will be routed through a secure socket to port 9000 in the dyno. To stop port forwarding : CTRL+C

Usage with Docker#

Heroku exec is not officially supported and requires the following config :

  • Create a new file heroku-exec.sh :

[ -z "$SSH_CLIENT" ] && source <(curl --fail --retry 3 -sSL "$HEROKU_EXEC_URL")

  • Include it in /app/.profile.d directory in Dockerfile :

ADD ./.profile.d /app/.profile.d

  • Ensure the default shell is Bash by including the following line in Dockerfile :

RUN rm /bin/sh && ln -s /bin/bash /bin/sh

Disabling the feature#

$ heroku features:disable runtime-heroku-exec

Remove the Heroku Exec buildpack#

$ heroku buildpacks:remove heroku/exec

Limitations#

Connection#

  • Each Heroku Exec connection lasts a maximum of one hour
  • Not supported in Shield Private Spaces
  • Not enabled for one-off dynos

Environment variables#

The SSH session created by Heroku Exec will not have the config vars set as environment variables (i.e., env in a session will not list config vars set by $ heroku config:set) In this case, environment variables must be exported, copied and pasted into the console when exec like the following :

`$ heroku config -s > env`
`$ cat env | sed 's/^/export /'`
< copy the output from the cat cmd >
`$ heroku ps:exec -a <app_name>`
< paste the output from the cat cmd >
## Data backup and restore for local use
  • For Docker db container

    $ rm latest.dump $ heroku pg:backups:capture -a <app_name> $ heroku pg:backups:download -a <app_name> $ docker cp latest.dump <db_container>:/latest.dump \$ docker exec -i <db_container> pg_restore --verbose --clean --no-acl --no-owner -U postgres -d <local_db_name> /latest.dump

  • For local db (i.e using pgAdmin4)

    $ rm latest.dump $ heroku pg:backups:capture -a <app_name> $ heroku pg:backups:download -a <app_name> $ pg_restore --verbose --clean --no-acl --no-owner -h localhost -U postgres -d <local_db_name> latest.dump

App performance#

  • Worker Dynos, Background jobs and Queueing

  • RabbitMQ and Celery configuration

    Set CELERY_RESULT_BACKEND = None and BROKER_POOL_LIMIT = 1

    If a Error R14 (Memory quota exceeded) is returned, just upgrade the worker's dynos plan

  • Enable HTTP cache headers

  • Use AWS S3 to store static assets and file uploads

  • Optimize Dyno usage

    • Use a concurrent web server
    • Set up instrumentation to measure the impact of load on the application
    • Observe the application’s performance, and adjust the concurrency as necessary

Recommended Features#

  • Add a custom domain
  • Provision Heroku Postgres
  • Create a Team
  • Create a pipeline
  • Setup a Heroku CI
  • Use WebSocket protocol

Debugging#

  • Logging : runtime logs (app, system, API and add-on) & build logs
  • Heroku error codes
  • Application metrics
  • Production check : Dyno redundancy, DNS & SSL, Heroku Postgres, visibility & monitoring
Last updated on by Youssouf El Azizi