spring-bootgithub-actionsspring-boot-maven-pluginbuildpackgithub-package-registry

Configure custom container image LABEL using Cloud Native Build Packs/Paketo.io with spring-boot-maven-plugin for GitHub Container Registry link


I created a simple Spring Boot application using https://start.spring.io/. Now I want to use Paketo.io / Cloud Native Build Pack support of the spring-boot-maven-plugin to build a container image and push it to the GitHub Container Registry using GitHub Actions.

My pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.jonashackt</groupId>
    <artifactId>helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>helloworld</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>15</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

I successfully managed to create a Docker image using the mvn spring-boot:build-image command inside my GitHub Actions workflow. I also successfully pushed it to the GitHub Container Registry (following this guide). Here's my build.yml workflow:

name: publish

on: [push]

jobs:
  publish:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Set up JDK 15
      uses: actions/setup-java@v1
      with:
        java-version: 15

    - name: Build the hello-world Docker image
      run: |
        echo 'Login to GitHub Container Registry'
        echo $CR_PAT | docker login ghcr.io -u jonashackt --password-stdin

        echo 'Build a container image from our Spring Boot app using Paketo.io / Cloud Native Build Packs'     
        mvn spring-boot:build-image --batch-mode --no-transfer-progress

        echo 'tag Paketo build image to have the right GitHub Container Registry coordinates'
        docker tag helloworld:0.0.1-SNAPSHOT ghcr.io/jonashackt/helloworld:latest
        
        docker push ghcr.io/jonashackt/helloworld:latest
      env:
        CR_PAT: ${{ secrets.CR_PAT }}

Unfortunately, the Container Registry image isn't linked to the GitHub repository, since this has to be done with a specific OCI compliant LABEL inside the Dockerfile:

LABEL org.opencontainers.image.source="https://github.com/jonashackt/helloworld"

How could one configure this LABEL using Cloud Native Build Packs / Paketo together with the spring-boot-maven-plugin?


Solution

  • As the spring-boot-maven-plugin transparently wraps Paketo.io / Cloud Native Build Packs, the best way is to start in https://paketo.io/docs. There's a section on how to apply custom labels to application images:

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

    As org.opencontainers.image.source is a OCI-specific label, the the Image Labels Buildpack will set the correct label for us. All we have to do, is to pass an environment variable to the Paketo build that we prefix with BP_OCI_. Have a look at the possible OCI specific labels in the docs. For example, if we run the following Paketo build:

    pack build spring-boot-buildpack
      --path . \
      --builder paketobuildpacks/builder:base \
      --env "BP_OCI_DESCRIPTION=Demo Application"
    

    The resulting application image will have a LABEL defined with the value org.opencontainers.image.description Demo Application. So in order to set org.opencontainers.image.source we need to define the environment variable BP_OCI_SOURCE for our Paketo build!

    But as we use the spring-boot-maven-plugin here, we need to somehow configure this environment variable inside our pom.xml, since we don't directly interact with the Paketo CLI. The the documentation tells us that we can use the image.env tags inside a configuration tag to define

    Environment variables that should be passed to the builder.

    In order to configure the OCI-specific LABEL org.opencontainers.image.source https://github.com/yourGitHubUserOrOrgaName/yourRepositoryName to the application image build by Paketo using the spring-boot-maven-plugin, add the following tags to your pom.xml (here's also a fully comprehensible example project including a pom.xml):

    <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <image>
                            <env>
                                <BP_OCI_SOURCE>https://github.com/yourGitHubUserOrOrgaName/yourRepositoryName</BP_OCI_SOURCE>
                            </env>
                        </image>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    

    Now your image gets linked to your GitHub repository. If you look at your account's packages and click into the build image, you should see all your README.md information mapped like this:

    enter image description here