This topic tells you how to configure Tanzu Buildpacks with kp CLI.

Configuration examples will use the Paketo sample applications.

Examples assume that the root of this repository is the working directory:

git clone https://github.com/paketo-buildpacks/samples
cd samples

Optionally, you can create Tanzu Build Service images from local binaries using the --local-path flag. For more information, see the Tanzu Build Service documentation.

The kp CLI is used throughout the examples. You can download kp from the Broadcom Support Portal under VMware Tanzu Build Service. kp is for use with Tanzu Build Service which is the easiest way to use Tanzu Buildpacks.

Examples assume that you have the Tanzu Build Service default cluster builder, which you install using kp import with the descriptor published under VMware Tanzu Build Service Dependencies on the Broadcom Support Portal. You may set a different cluster builder by setting the --cluster-builder my-builder flag.

Types of Configuration

You can configure Tanzu buildpacks by using following mechanisms:

Environment Variables

Build-time Environment Variables

Users may configure the build by setting variables in the buildpack environment. The names of variables accepted by the Tanzu buildpacks at build-time are either prefixed with BP_ or have well-known conventional meanings outside of Tanzu (e.g. http_proxy).

The following example uses an environment variable to configure the JVM version installed by the Java Buildpack.

kp image save samples-java  \
  --tag registry.example.com/project/sample-java-app \
  --git https://github.com/paketo-buildpacks/samples \
  --sub-path "java/jar" \
  --env BP_JVM_VERSION=8

During the build process, a buildpack may invoke other programs that accept configuration through the environment. Users may configure these tools as they would normally. For example, the following command configures the JVM memory settings for the JVM running Maven using MAVEN_OPTS:

kp image save samples-java  \
  --tag registry.example.com/project/sample-java-app \
  --git https://github.com/paketo-buildpacks/samples \
  --sub-path "java/maven" \
  --env "MAVEN_OPTS=-Xms256m -Xmx512m"

Runtime Environment Variables

Users may configure runtime features of the app image by setting environment variables in the app container. The names of variables accepted by buildpack-provided runtime components (e.g. profile scripts and processes types) are prefixed with BPL_ or have well-known conventional meanings outside of Tanzu (e.g JAVA_TOOL_OPTIONS).

The following example uses JAVA_TOOL_OPTIONS to set the server port of the sample application:

---
apiVersion: v1
kind: Deployment
metadata:
  name: samples-java
  labels:
    app: samples-java
spec:
  replicas: 1
  selector:
    matchLabels:
      app: samples-java
  template:
    metadata:
      labels:
        app: samples-java
    spec:
      containers:
        - name: samples-java
          image: samples-java
          env:
          - name: JAVA_TOOL_OPTIONS
            value: "-Dserver.port=8082"
          ports:
          - protocol: TCP
            containerPort: 8082

Programs invoked at runtime, including the application itself, will accept environment as they would normally.

Image Embedded Environment Variables

Users may embed environment variables into the images created by using the Environment Variables buildpack. The Environment Variables buildpack looks for environment variables matching the pattern $BPE_*. When detected, the buildpack will modify the launch environment to adjust the specified variables. This is a good way to set non-sensitive configuration values such as defaults or modify environment variables that you do not need users to set.

The buildpack supports the following actions on environment variables:

Environment Variable Name Description
$BPE_<NAME> set $NAME to value (same as override)
$BPE_APPEND_<NAME> append value to $NAME
$BPE_DEFAULT_<NAME> set default value for $NAME
$BPE_OVERRIDE_<NAME> set $NAME to value
$BPE_PREPEND_<NAME> prepend value to $NAME

For more information about actions, see the environment variable modification rules from the buildpacks spec in GitHub.

You can also change the delimiter used when appending or prepending by setting $BPE_DELIM_<NAME> for a particular variable name. It will default to an empty string (i.e. no delimiter). An example of using this would be to append to PATH or LD_LIBRARY_PATH, which are colon delimited.

Important

Do not embed sensitive credentials or information using the environment variables buildpack. This information is added to the image generated by your build tool, so anyone with access to the image can see what you embed using this buildpack.

buildpack.yml

Many Tanzu buildpacks accept configuration from a buildpack.yml file if one is present at the root of the application directory.

For example, to configure the NodeJS version installed by the NodeJS Buildpack, create a file named buildpack.yml in the nodejs/yarn directory in the samples repo.

nodejs:
  version: 12.12.0

Next, execute the build as normal and observe the that the specified version of NodeJs is installed.

kp image save samples-nodejs \
  --tag registry.example.com/project/sample-nodejs-app \
  --git https://github.com/paketo-buildpacks/samples \
  --sub-path "nodejs/yarn"

Bindings

Why bindings?

Some Tanzu Buildpacks and components installed by the Tanzu Buildpacks accept credentials and other secrets using bindings at build and runtime. Commonly, bindings provide the location and credentials needed to connect to external services.

Some categories of external services one might want to bind at build-time include:

  • Private artifact repositories.
  • SaaS security scanning tools.

For example, the Maven buildpack accepts the location and credentials need to connect to a private Maven repository in a binding.

Some categories of external services one might want to bind at runtime include:

  • APM servers.
  • Data Services.
  • OAuth2 providers.

For example, the Spring Boot Buildpack will install Spring Cloud Bindings which is capable of auto-configuring Spring Boot application configuration properties to connect the application to a variety of external services, when a binding is provided at runtime.

What is a binding?

A Binding contains:

  1. A name. Indentifies a particular binding. The name typically does not affect build or runtime behavior but may be used to reference a specific binding in output such as log messages.

  2. A type or kind. Indicates what type of credentials the binding contains. For example, a binding of type ApplicationInsights contains the credentials needed to connect to Azure Application Insights.

  3. An optional provider. Indicates the source of the binding. For example, in a PaaS context, a specific service broker might provide the binding.

  4. key-value pairs. These contain the configuration data. For example, an ApplicationInsights binding may contain a key-value pair with key InstrumentationKey.

Bindings must be presented to buildpacks as directories (typically volume mounted) on the container filesystem. The name of the directory provides the name of the binding. The contents of a binding can be provided using one of two specifications.

Tanzu Buildpacks will look for bindings in the /platform/bindings directory at build-time and in $SERVICE_BINDING_ROOT or $CNB_BINDINGS directory at runtime.

For example, the Java Buildpack accepts a binding with type equal to maven containing a key named settings.xml containing Maven settings. In the build container, the Maven Buildpack uses settings.xml if it finds either of the following on the filesystem, where either the type or kind file contains the string maven:

/platform
└── bindings
    └── <name>
        ├── settings.xml
        └── type

or

/platform
└── bindings
    └──<name>
        └── metadata
        |   └── kind
        └── secret
            └── settings.xml

How to use bindings?

The workflow for creating a binding and providing it to a build will depend on the chosen platform. Users of Tanzu Build Service should store key value pairs in a Kubernetes Secret and provide that secret and associated metadata to an Image as described in the Tanzu Build Service documentation.

It depends on the binding, but many bindings must also be provided at runtime as well. For example, if you are providing credentials for an APM agent, the binding must be present a build time so that the buildpack detects and installs the agent. It must also be present a runtime, because the APM credentials are not saved into the image. Thus they must be provided also at runtime, so the agent can use them.

Example:

Given a secret containing a runtime binding, Tanzu Build Service users can provide the binding to the app image using a pod spec like this:

---
apiVersion: v1
kind: Pod
metadata:
  name: samples-ca-certificates
spec:
  containers:
    - name: samples-ca-certificates
      image: samples-ca-certificates
      env:
      - name: SERVICE_BINDING_ROOT
        value: "/bindings"
      volumeMounts:
      - name: custom-ca-certs
        mountPath: "/bindings/ca-certificates"
        readOnly: true
  volumes:
  - name: custom-ca-certs
    secret:
      secretName: custom-ca-certs

Tanzu Procfile Buildpack

Tanzu users may override buildpack-provided types or augment the app-image with additional process types using a Procfile. Procfile support is provided by the Paketo Procfile Buildpack. The Procfile Buildpack will search for a file named Procfile at the root of the application. Procfiles must adhere to the following schema:

<type>: <command>

If a given language family buildpack does not contain the Procfile Buildpack it can be explicitly appended at runtime.

Example: A Hello World Procfile

The following adds a process with type equal to web and which is the default process. It is necessary to use web because changing the default process type is not supported yet with Tanzu Build Service.

echo "web: echo hello world" > nodejs/yarn/Procfile
kp image save samples-nodejs \
  --tag registry.example.com/project/sample-nodejs-app \
  --git https://github.com/paketo-buildpacks/samples \
  --sub-path "nodejs/yarn"
docker run samples-nodejs # should print "hello world"

Note that the builder used in this example must have an order group with Node.js and the Procfile buildpacks. If the Procfile does not execute in this example, it is because it is not present in the selected order group.

Building Behind a Firewall

Proxy Configuration

Proxy configuration is possible. For more information, see the Tanzu Build Service documentation.

Dependency Mappings

Tanzu Buildpacks may download dependencies from the Internet. For example, the Java Buildpack downloads the BellSoft Liberica JRE from the Liberica github releases by default.

If a dependency URI is inaccessible from the build environment, you can use a binding to map a new URI to the dependency. This allows organizations to upload a copies of vetted dependencies to an accessible location and provide developers and CI/CD pipelines with configuration pointing the buildpack at the accessible dependencies.

The URI mappings can be configured with one or more bindings of type dependency-mapping. Each key value pair in the binding should map the sha256 of a dependency to a URI. You can find information about the dependencies a buildpack downloads, including the sha256 and the current default uri, in the buildpack.toml of each component buildpack.

Example: Mapping the JRE to an internal URI

For example, to make the Bellsoft Liberica JRE dependency accessible available to builds in an environment where Github is inaccessible, an operator must:

  1. Find the sha256 and default uri for the desired dependency in buildpack.toml of the Bellsoft Liberica buildpack. Example values:

    • sha256: b4cb31162ff6d7926dd09e21551fa745fa3ae1758c25148b48dadcf78ab0c24c
    • uri: https://github.com/bell-sw/Liberica/releases/download/11.0.8+10/bellsoft-jre11.0.8+10-linux-amd64.tar.gz
  2. Download the dependency from the uri and upload it to a location on the internal network that is accessible during the build.

  3. Create a binding with:

    • type equal to dependency-mapping
    • A key/value pair where the key is equal to the sha256 of the dependency and the value is equal to the new URI.
  4. Configure all builds with this binding.

CA Certificates

Additional CA certificates may be added to the system truststore using the Paketo CA Certificates Buildpack.

CA certificates can be provided at both build and runtime with a binding of type ca-certficates. Each key value pair in the binding must map a certificate name to a single PEM encoded CA certificate.

<binding-name>
├── <cert file name>
└── type

If a given language family buildpack does not contain the Paketo CA Certificates Buildpack you may customize your builder to include it. The Paketo CA Certificates Buildpack must be added at the beginning of each order group.

Example: Adding a CA Certificate at Runtime

The samples repository contains a simple Golang application that will make a HEAD request to a provided URL.

For Tanzu Build Service, follow the instructions for service bindings. This results in a YAML configuration that looks similar to the following, which you can apply using kubectl apply:

apiVersion: kpack.io/v1alpha1
kind: Image
metadata:
  name: my-ca-certs-binding
spec:
  tag: registry.example.com/project/sample-go-app
  builder:
    kind: ClusterBuilder
    name: default
  source:
    git:
      url: https://github.com/paketo-buildpacks/samples.git
      revision: main
      subPath: ca-certificates
  build:
    bindings:
    - name: ca-certs
      secretRef:
        name: ca-certs
      metadataRef:
        name: ca-certs-binding-metadata
---
apiVersion: v1
kind: Secret
metadata:
  name: ca-certs
type: Opaque
stringData:
  <your-ca.pem>: <insert PEM encoded cert>
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ca-certs-binding-metadata
data:
  type: ca-certificates
  provider: sample

The provided sample contains a simple Golang application that will make a HEAD request to a provided URL. Build the application using the CA Certificates buildpack.

Run the sample application, providing the binding, and passing the URL as a positional argument.

docker run --rm \
  --env SERVICE_BINDING_ROOT=/bindings \
  --volume "$(pwd)/ca-certificates/binding:/bindings/ca-certificates" \
  registry.example.com/project/sample-go-app <url>

The expected output is SUCCESS!.

Deactivating CA Certificates

If a language family buildpack contains the Paketo CA Certificates Buildpack, the CA Certificates Buildpack will always pass detection so that certificates can be provided dynamically at runtime.

To opt out of this behavior all together, the BP_ENABLE_RUNTIME_CERT_BINDING environment variable can be set to false at build-time. This deactivates the ability to set certificates at runtime. The CA Certificates Buildpack will then only detect if a certificate binding is provided at build-time.

Applying Custom Labels

Tanzu users may add labels to the application image using the Image Labels Buildpack.

Environment variables prefixed with BP_OCI_ can be used to set OCI-specific. For example, if BP_OCI_AUTHORS is set at build-time, the Image Labels Buildpack will add a label to the image with key org.opencontainers.image.authors and value equal to the value of $BP_OCI_AUTHORS.

Users may contribute arbitrary labels by providing a collection of space-delimited key-value pairs with the BP_IMAGE_LABELS environment variable. Values containing spaces can be quoted.

If a given language family buildpack does not contain the Image Labels Buildpack it can be explicitly appended at runtime.

Example: Add Custom Labels

kp image save samples-nodejs \
  --git https://github.com/paketo-buildpacks/samples \
  --sub-path "nodejs/yarn" \
  --env "BP_OCI_DESCRIPTION=Demo Application" \
  --env 'BP_IMAGE_LABELS=io.tanzu.example="Adding Custom Labels"'
docker inspect samples-nodejs | jq '.[].Config.Labels["org.opencontainers.image.description"]' # should print "Demo Application"
docker inspect samples-nodejs | jq '.[].Config.Labels["io.tanzu.example"]' # should print "Adding Custom Labels"

Configuring Locale

By default, an image created using Tanzu buildpacks will not have a specific locale set. If you run locale, you'll end up with these settings:

LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

If you wish to set a locale, you may do so when you run the image by setting the corresponding environment variable. For example, with Docker one could execute docker run -e LANG=en_US.utf8 ... to change the locale.

This isn't always necessary but can impact output from your application. For example if you have an application that writes unicode characters to STDOUT/STDERR and you go to view those, possibly with docker logs, they will not display correctly unless you have a locale set that supports unicode, like UTF-8 in the preceeding example.

check-circle-line exclamation-circle-line close-line
Scroll to top icon