1

We're using Heroku Buildpacks inside a GitLab CI/CD pipeline by triggering a job running the heroku builder image and then invoking the /cnb/lifecycle/creator directly, instead of using the pack CLI. This is because be can't use docker in docker on our container orchestrator.

This all works fine and dandy, but we're facing the problem of not being able to specify any custom labels that will be added to the produced image. By default, these labels are added:

  • io.buildpacks.lifecycle.metadata
  • io.buildpacks.build.metadata
  • io.buildpacks.project.metadata

But we'd also like to add the following labels:

  • org.opencontainers.image.revision
  • org.opencontainers.image.url
  • org.opencontainers.image.source
  • org.opencontainers.image.version
  • org.opencontainers.image.licenses
  • org.opencontainers.image.authors

Unfortunately there seems to be no way to specify this. The creator doesn't offer any configuration parameter to do this, neither the pack CLI as far as I could tell. When using Paketo buildpacks, there is indeed a designated buildpack to solve this: https://github.com/paketo-buildpacks/image-labels

Is there any way to do something similiar when using Heroku buildpacks?

VeryDogeWow
  • 142
  • 7
  • Have you tried using the paketo-buildpacks/image-labels buildpack with the heroku builder? if not, i'll add an answer explaining how to – codefinger Mar 29 '22 at 14:09

2 Answers2

1

You can use the Paketo image-labels buildpack with the Heroku buildpacks. Here's an example of doing this from the pack CLI:

$ pack build --builder heroku/buildpacks:20 --buildpack paketo-buildpacks/image-labels my-app

With the CLI you can add more --buildpack options as needed.

If you want to codify this, you can create a project.toml and use the io.buildpacks.post.group to always run the image-labels buildpack at the end.

If you're using creator binary, you can provide it a group.toml https://github.com/buildpacks/spec/blob/main/platform.md#inputs-3

codefinger
  • 10,088
  • 7
  • 39
  • 51
  • Thanks for your answer. I have some follow-up questions: How can I specify this without using the pack CLI? I've tried adding a custom project.toml but it seems the creator executable just ignores that. – VeryDogeWow Mar 29 '22 at 14:43
  • 1
    Yea, you can pass a group.toml to creator https://github.com/buildpacks/spec/blob/main/platform.md#inputs-3 – codefinger Mar 30 '22 at 18:54
  • I'm facing the same problem with the group.toml. I've added the paketo image labels buildpack to the group.toml and also set the CNB_GROUP_PATH to the correct value. But the buildpack isn't being used. I've also manually added the paketo image labels buildpack to the builder image, but to no avail. Any help would be much appreciated... – VeryDogeWow Mar 31 '22 at 09:57
  • Okay I found the issue. Apparently the detector overrides the group.toml. So in order for this to work one must call each executable in sequence and then add the custom values to the group.toml after the detector has run. Thanks! – VeryDogeWow Mar 31 '22 at 13:45
  • @VeryDogeWow, can you share the details with example `group.toml` – kiran Sep 16 '22 at 01:01
  • @kiran I've added a more detailed answer – VeryDogeWow Sep 19 '22 at 08:31
1

Here's a more detailed answer on how to achieve this:

  1. Create a custom builder image which contains heroku buildpacks as well as the desired image labels buildpack by paketo
  2. Run the lifecycle executables in the specified order manually
  3. Add an entry for the image labels buildpack to the group.toml AFTER the detector has run

Heres an example Dockerfile for building a custom builder image:

# paketo
FROM paketobuildpacks/builder:base as paketo

# heroku
FROM heroku/builder-classic:22

USER root

COPY --from=paketo /cnb/buildpacks/paketo-buildpacks_image-labels /cnb/buildpacks/paketo-buildpacks_image-labels

COPY group.toml /opt/group.toml

SHELL ["/bin/bash", "-c"]

USER 1000

This is what the file under /opt/group.toml looks like:

[[group]]
    description = "A Cloud Native Buildpack that enables configuration of labels on the created image"
    homepage = "https://github.com/paketo-buildpacks/image-labels"
    id = "paketo-buildpacks/image-labels"
    keywords = ["image-labels", "labels"]
    name = "Paketo Image Labels Buildpack"
    version = "4.2.0"
    sbom-formats = ["application/vnd.cyclonedx+json", "application/vnd.syft+json"]
    api = "0.7"

Then you can run the lifecycle as follows:

export CNB_LAYERS_DIR=${BP_LAYERS_PATH}
export CNB_GROUP_PATH=${BP_LAYERS_PATH}/group.toml

/cnb/lifecycle/detector -layers=${BP_LAYERS_PATH} -platform=${BP_PLATFORM_PATH} -app=.

# add additional logic for image-label-buildpack
[ -f /opt/group.toml ] && echo "$(cat /opt/group.toml)" >> ${CNB_GROUP_PATH}

export BP_LAST_VERSION=${BP_IMAGE_VERSION}
/cnb/lifecycle/analyzer -uid=$(id -u) -gid=0 -cache-dir=${BP_CACHE_PATH} -layers=${BP_LAYERS_PATH} -analyzed=${BP_LAYERS_PATH}/analyzed.toml ${BP_REGISTRY}/${BP_IMAGE_NAME}:${BP_LAST_VERSION}

/cnb/lifecycle/restorer -uid=$(id -u) -gid=0 -cache-dir=${BP_CACHE_PATH} -layers=${BP_LAYERS_PATH} -group=${BP_LAYERS_PATH}/group.toml

/cnb/lifecycle/builder -layers=${BP_LAYERS_PATH} -platform=${BP_PLATFORM_PATH} -app=. -group=${BP_LAYERS_PATH}/group.toml

/cnb/lifecycle/exporter -uid=$(id -u) -gid=0 -cache-dir=${BP_CACHE_PATH} -layers=${BP_LAYERS_PATH} -app=. -analyzed=${BP_LAYERS_PATH}/analyzed.toml -run-image=${BP_RUN_IMAGE} ${BP_REGISTRY}/${BP_IMAGE_NAME}:${BP_IMAGE_VERSION}

Make sure to fill the env variables with sane values as defined by the platform spec.

VeryDogeWow
  • 142
  • 7