docs community resources blog github
Edit

How to Create a Custom Stack

Preface

This documentation explains how to create a custom stack based off of the existing Paketo stacks. Check out the stacks concept page for more information about what a stack is and the Paketo offerings.

It’s recommended to use an existent Paketo stack offering, over creating a custom stack in order to leverage the full range of Paketo security patching and compliance standards.

In some cases, a custom stack image may be useful for users who may need an extra system library or user ID, for example. The Cloud Native Buildpacks project already has documentation for creating a stack from scratch, but for some Paketo users it may be simpler and less error-prone to build upon the stack we already provide. It’s recommended to read the CNB documentation regardless, because there are a lot of details and explanations there that still apply.

Create a custom stack image based off of a Paketo Stack

Using docker build

This guide assumes you know the basics of stacks from the stacks concept page.

  1. Create a Dockerfile and define the base image as one of the Paketo stacks. For example:
    FROM paketobuildpacks/build-jammy-tiny as base
    
    copy to clipboard
    Copied!

There are multiple stack variants to choose from (tiny, base, full). Check out the stack’s Github repository (for example, github.com/paketo-buildpacks/jammy-tiny-stack for the Jammy Tiny Stack) stack directory to see the definitions for the build and run images.

  1. Add your desired custom stack change to the Dockerfile such as labels, environment variables, and/or packages. There are examples in the CNB documentation . Note that the changes need to abide by the CNB spec. For example, setting the CNB_USER_ID to root isn’t allowed.

  2. Build the stack image with docker build . -t <stack-name>-<run or build>:<tag> --target <target> for both the build and run images.

  3. Push the stack images to a registry with docker push

Using jam create-stack

Prerequisites

You will need the following tools installed on your machine:

  1. Create a Dockerfile for the build and run stack images, as in steps 1 and 2 above.

  2. Create a stack.toml, which should resemble the following:

id = "io.buildpacks.stacks.jammy.tiny"

platforms = ["linux/amd64"]

[build] 
  dockerfile = "<path/to/build/Dockerfile>"
  gid = 1000
  shell = "/bin/bash"
  uid = 1000

  [build.args]
    sources = """
    deb http://archive.ubuntu.com/ubuntu jammy main universe multiverse
    deb http://archive.ubuntu.com/ubuntu jammy-updates main universe multiverse
    deb http://archive.ubuntu.com/ubuntu jammy-security main universe multiverse
    """

    # List of packages which should be included in the stack build image
    packages = """\
    <some-package> \
    <another-package> \
    """

[run]
  dockerfile = "<path/to/run/Dockerfile>"
  gid = 1000
  shell = "/sbin/nologin"
  uid = 1000

  [run.args]
    sources = """
    deb http://ports.ubuntu.com/ubuntu-ports/ jammy main universe multiverse
    deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main universe multiverse
    deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main universe multiverse
    """

    # List of packages which should be included in the stack run image
    packages = """\
    <some-package> \
    <another-package> \
    """

[deprecated]
  legacy-sbom = true
  mixins = true
copy to clipboard
Copied!
  1. Create the stack with the jam CLI:
jam create-stack --config stack.toml --build-output <name>.oci --run-output <name>.oci
copy to clipboard
Copied!
  1. Use skopeo to copy the OCI archives to the desired registry:

    To copy the archives to a remote registry:

skopeo copy oci-archive:///<path/to/oci/archive/> docker://<registry-image-location>:<tag>
copy to clipboard
Copied!

To copy the archives to your local Docker daemon:

skopeo copy oci-archive:///<path/to/oci/archive> docker-daemon:<stack-image-name>:<tag>
copy to clipboard
Copied!

Create a custom builder with the custom stack

Check out the builder documentation for details on builders.

  1. Clone the builder you want to use, and modify the builder.toml file. For example, if you have built a custom stack based off of the Paketo Jammy Tiny stack, you will want to add it to the Jammy Tiny builder builder.toml file. Modify the bottom [stack] section to point to the registry location of the build and run images you have pushed to a registry. The id should match the stack ID if you specified one in the Dockerfile, or in the base image you used. It will be something along the lines of io.buildpacks.stacks.jammy (or io.buildpacks.stacks.jammy.tiny if using Tiny stack). This ID implies compatibility with the official Paketo stack with that label.
  2. Create the builder with the pack CLI.
    pack builder create <builder-name> —config <path to builder.toml>
    
    copy to clipboard
    Copied!
  3. Ensure the buildpacks of interest support the wildcard (“*”) stack or support the stack ID you provided in the builder.toml by checking the buildpack stacks section. For example, the node-engine buildpack supports both stacks with ID io.buildpacks.stacks.jammy and *.
  4. Perform builds with the newly created builder image, which uses the custom stack images.
Edit

Last modified: December 6, 2024