Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Extending Heroku
  • Developing Buildpacks
  • Buildpack API

Buildpack API

English — 日本語に切り替える

Last updated October 04, 2022

Table of Contents

  • Buildpack API
  • .profile.d scripts
  • Composing multiple buildpacks
  • Caching
  • Stacks
  • Binaries
  • Publishing and Sharing Buildpacks
  • Example Buildpacks
  • Problems or questions

Buildpacks are the scripts that power app builds on Heroku. Check out the Buildpacks article for an overview of what role buildpacks play on the Heroku platform.

Buildpack API

We encourage buildpack developers to use sh or bash to ensure compatibility with future Heroku stacks.

A buildpack consists of three scripts:

  • bin/detect: Determines whether to apply this buildpack to an app.
  • bin/compile: Used to perform the transformation steps on the app.
  • bin/release: Provides metadata back to the runtime.

bin/detect

Usage

bin/detect BUILD_DIR

The name sent to stdout will be displayed as the application type during push.

Summary

This script takes BUILD_DIR as a single argument and must return an exit code of 0 if the app present at BUILD_DIR can be serviced by this buildpack. If the exit code is 0, the script must print a human-readable framework name to stdout.

Example

#!/bin/sh

# this pack is valid for apps with a hello.txt in the root
if [ -f $1/hello.txt ]; then
  echo "HelloFramework"
  exit 0
else
  exit 1
fi

bin/compile

Usage

bin/compile BUILD_DIR CACHE_DIR ENV_DIR

Summary

The contents of CACHE_DIR will be persisted between builds. You can cache the results of long processes like dependency resolution here to speed up future builds.

This script performs the buildpack transformation. BUILD_DIR will be the location of the app and CACHE_DIR will be a location the buildpack can use to cache build artifacts between builds.

All output received on stdout from this script will be displayed to the user (for interactive git-push builds) and stored with the build.

The application in BUILD_DIR along with all changes made by the compile script will be packaged into a slug.

ENV_DIR is a directory that contains a file for each of the application’s configuration variables. Config vars are made available as environment variables during execution of commands specified in the Procfile, as well as when running one-off processes.

The application config vars are passed to the buildpack as an argument (versus set in the environment) so that the buildpack can optionally export none, all or parts of the app config vars available in ENV_DIR when the compile script is run. Exporting the config can be scoped to only certain steps in the compile script or to the entire compile phase. The reason application config vars are passed to the compile script in individual files is to make it easier for buildpacks to correctly handle config vars with multi-line values

The name of the file is the config key and the contents of the file is the config value. The equivalent of config var S3_KEY=8N029N81 is a file with the name S3_KEY and contents 8N029N81.

Below is a Bash function demonstrating how to export the content of the ENV_DIR into the environment.

export_env_dir() {
  env_dir=$1
  acceptlist_regex=${2:-''}
  denylist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH)$'}
  if [ -d "$env_dir" ]; then
    for e in $(ls $env_dir); do
      echo "$e" | grep -E "$acceptlist_regex" | grep -qvE "$denylist_regex" &&
      export "$e=$(cat $env_dir/$e)"
      :
    done
  fi
}

Use the regular expressions to blocklist or allowlist config keys for export. For example, config vars like PATH can sometimes conflict with build tools so blocklisting that might be a good idea. allowlisting is recommended if you know that builds will only require a specific subset of config vars (like DATABASE_URL) to run.

The following environment variables are available during the compile phase:

  • STACK: see the Stacks section below for details on how to use this
  • SOURCE_VERSION: the “version” of the source code currently being built. For git-push builds, this is the git commit SHA-1 hash.

Style

Buildpack developers are encouraged to match the Heroku push style when displaying output.

-----> Main actions are prefixed with a 6-character arrow
       Additional information is indented to align

Whenever possible display the versions of the software being used.

-----> Installing dependencies with npm 1.0.27

Side effects

Buildpack developers should avoid generating side effects during the build. For example, it is not recommended to perform database migrations in the compile script.

Example

#!/bin/sh

indent() {
  sed -u 's/^/       /'
}

echo "-----> Found a hello.txt"

# if hello.txt has contents, display them (indented to align)
# otherwise error

if [ ! -s $1/hello.txt ]; then
  echo "hello.txt was empty"
  exit 1
else
  echo "hello.txt is not empty, here are the contents" | indent
  cat $1/hello.txt
fi | indent

bin/release

Usage

bin/release BUILD_DIR

Summary

addons will only be applied the first time an app is deployed.

BUILD_DIR will be the location of the app.

This script returns a YAML formatted hash with two keys:

  • addons is a list of default addons to install.
  • default_process_types is a hash of default Procfile entries.

This script will only be run if present.

Note: The buildpack’s export script is not sourced prior to bin/release being run, so any environment variables set in export will not be available (such as those adding runtime binaries to PATH). If they are required, the export script will need to be sourced manually.

Example

#!/bin/sh

cat << EOF
---
addons:
  - heroku-postgresql
default_process_types:
  web: bin/node server.js
EOF

Instead of using default_process_types, you may also write a default Procfile if one isn’t provided.

.profile.d scripts

During startup, the container starts a bash shell that source’s all .sh scripts in the .profile.d/ directory before executing the dyno’s command. An application’s config vars will already be present in the environment at the time the scripts are sourced.

This allows buildpacks to manipulate the initial environment for all dyno types in the app. Potential use cases include defining initial config values like $PATH by exporting them into the environment, or performing other initialization steps necessary during dyno startup.

Like the standard Linux /etc/profile.d shell startup files, these must be bash scripts, and their filenames must end in .sh. No guarantee is made regarding the order in which the scripts are sourced.

Scripts in .profile.d/ should only be written by buildpacks. If you need to perform application-specific initialization tasks at the time a dyno boots, you should use .profile scripts, which are guaranteed to run after the scripts in .profile.d/.

Example .profile.d/mybuildpack-defaults.sh

It is recommended to prefix script filenames using a common identifier, e.g. based on the name of the buildpack. Otherwise, collisions are possible if an application uses multiple buildpacks that use the same script filenames.

# add vendor binaries to the path
export PATH=$PATH:$HOME/vendor/bin

# set a default LANG if it does not exist in the environment
export LANG=${LANG:-en_US.UTF-8}

To avoid overwriting an existing config var value, use a technique like the ${var:-default} parameter substitution shown above for the $LANG variable.

Composing multiple buildpacks

An app can be composed by multiple buildpacks which run in sequence. In order to provide an environment for subsequent buildpacks, a buildpack can create a $buildpack_dir/export script to be executed before the following buildpack is run.

For example, the Node.js buildpack uses this to provide a node binary for subsequent buildpacks to use.

Caching

Use caution when storing large amounts of data in the CACHE_DIR as the full contents of this directory is stored in S3 and must be network-transferred back and forth each time this app is deployed. A large CACHE_DIR can introduce a significant delay to the build process.

The bin/compile script will be given a CACHE_DIR as its second argument which can be used to store artifacts between builds. Artifacts stored in this directory will be available in the CACHE_DIR during successive builds. This build cache is available only during slug compilation, and is specific to the app being built.

If the buildpack does intend to use a cache, it should create the CACHE_DIR directory if it doesn’t exist.

Buildpacks often use this cache to store resolved dependencies to reduce build time on successive deploys.

Heroku users can use the heroku-builds plugin to clear the build cache created by the buildpack they use for their app.

Stacks

Heroku supports multiple OS base images, called stacks.

If you’re maintaining a buildpack, it’s your responsibility to make sure that the buildpack can create slugs that works on all the stacks that Heroku supports. When Heroku runs buildpacks to create slugs for an app, the build is always run in a dyno using the same stack as the app that the build is running for. In addition, a STACK environment variable is available during the compile phase so that a buildpack can determine the destination stack for the build. Example STACK values are heroku-18, heroku-20 and heroku-22.

If your buildpack does not support a particular stack, the compile script can optionally print an error and exit with a non-zero exit code. Heroku recommends supporting all stacks, however.

Buildpacks should use the STACK variable to selectively pull binaries and other dependencies appropriate for that stack. Typically, binaries that are vendored in by buildpacks have to be built in different versions for each stack to ensure compatibility. See the Binaries section below for details.

Binaries

A buildpack is responsible for building a complete executable package around the app. This may necessitate including language VMs and other system dependencies that are needed by the app to run.

When building and packaging dependencies, make sure they are compatible with the stacks currently in use on Heroku. It may be necessary to compile and distribute dependencies separately for each stack and vendor in the appropriate set for the app currently being built. One way to do that is to build dependencies in Heroku dynos, for example by using heroku run.

Publishing and Sharing Buildpacks

If you would like to share your buildpack with the Heroku community, you can register your buildpack. After registering, your buildpack will be displayed in the heroku buildpacks:search CLI command and Heroku Elements (late 2018).

Example Buildpacks

The easiest way to get started creating a buildpack is to examine or fork one of the many existing buildpacks:

  • Default Buildpacks
  • Third-party Buildpacks

Problems or questions

If you’re trying to create a buildpack and run into problems or have questions along the way, please submit them to Stack Overflow.

Keep reading

  • Developing Buildpacks

Feedback

Log in to submit feedback.

Testpack API Buildpack Registry

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences