Use a Custom Buildpack

If you need to deploy a technology which is not supported by Scalingo, you can use an open-source buildpack or a buildpack you have developed.

To achieve this, you must define the following environment variable in the environment of the concerned application: BUILDPACK_URL.

Example:

BUILDPACK_URL=https://github.com/cloudfoundry/java-buildpack

Then the deployment logs contain:

<-- Start deployment of my-app -->
-----> Cloning custom buildpack: 'https://github.com/cloudfoundry/java-buildpack'

-- SNIP --

If you need to test a branch of a custom buildpack different than master, specify its name at the end of the URL:

BUILDPACK_URL=https://github.com/cloudfoundry/java-buildpack#branch_name

Build a Custom Buildpack

Our execution stack is public and can be found as a docker image on the Docker Hub. Its name is scalingo/scalingo-22. The base image is based on Ubuntu 22.04. The Scalingo stack contains every tool from the ubuntu:22.04 Docker image.

Run the following command to start a container in the same environment a custom buildpack will be executed:

docker run --pull always --rm --interactive --tty -e STACK=scalingo-22 -v /path/to/custom-buildpack:/buildpack -v /path/to/application:/build scalingo/scalingo-22:latest bash

Then, export the environment variables from your application into the Docker container, and create the folders that will be used by the buildpack scripts:

mkdir /tmp/{cache,env}

If you need to build third-party binaries, you are assured that they will work on the Scalingo platform.

Architecture of a Buildpack

A buildpack has three mandatory entrypoints:

  • bin/detect: exit with success (return code is 0) if the buildpack applies to the current application.
  • bin/compile: installs the technology.
  • bin/release: handles some metadata.

All these entrypoints are usually Bash script.

Script detect

The purpose of the script located in bin/detect is to detect if the buildpack applies to the application. It takes the build directory in argument. If the buildpack is applicable, the script must print on the standard output the name of the technology and return with the code 0.

Here is an example of such script which detects a buildpack as applicable for our technology if the file biniou.yml is present at the root of the application.

#!/bin/bash

BUILD_DIR=${1:-}

if [ -f "${BUILD_DIR}/biniou.yml" ]; then
  echo "My Wonderful Technology" && exit 0
fi

echo "no" && exit 1

Script compile

The purpose of the script located in bin/compile is to actually compile the application. It is called with three arguments:

  • The build directory: contains the code of the application.
  • The cache directory: used to store information one wants to keep between two builds.
  • The environment directory: contains a file per environment variable defined. For instance, an environment variable TEST=1234 leads to a file named TEST containing 1234.

Here is an example of a (very basic) compile script to compile a C application:

#!/bin/bash

BUILD_DIR=${1:-}
CACHE_DIR=${2:-}
ENV_DIR=${3:-}

echo "-----> Install gcc"
apt-get install --yes gcc

echo "-----> Compile the client application"
gcc -o my-app .

You can test this script in the Docker container with the command:

/buildpack/bin/compile /build /tmp/cache /tmp/env

Script release

The purpose of the script located in bin/release is to generate some metadata about the application. It takes the build directory in argument. It must print on the standard output a YAML file with a couple of keys:

  • addons: list of addons to install. It is only applied the first time an application is deployed.
  • config_vars: hash of default environment variables.
  • default_process_types: hash of default Procfile entries.

Here is an example of such script for a Node.js application:

#!/bin/bash

cat << EOF
---
addons:
  - scalingo-postgresql
config_vars:
  PATH: /app/bin:/app/vendor/nginx/sbin:/app/vendor/php/bin:/app/vendor/php/sbin:/usr/local/bin:/usr/bin:/bin
default_process_types:
  web: npm start
EOF

Script .profile.d

During startup of any container types, the container starts a Bash shell that sources all the files in the .profile.d/ folder, before executing the container start command. This allows a buildpack to customize the environment of the application. You can take inspiration of what has been done in Scalingo PHP buildpack with this folder.

Feel free to take inspiration from the various buildpacks proposed by Scalingo: https://github.com/Scalingo?utf8=%E2%9C%93&q=buildpack&type=&language=.

Private buildpack

If the url of BUILDPACK_URL is ending with .tar.gz or .tgz we will download and extract this archive. This allows you to host a private buildpack archive with typically a secret hash inside the url (for ex. https://myhostingsite/secret-hash-with-lot-letters-and-numbers.tgz).


Suggest edits

Use a Custom Buildpack

©2024 Scalingo