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:
But we'd also like to add the following labels:
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?
Here's a more detailed answer on how to achieve this:
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.