Article
Paketo Buildpacks provide a modern, declarative approach to building production-ready container images for Java applications without writing Dockerfiles. They automatically detect your application type, resolve dependencies, and create optimized container images following cloud-native best practices.
What are Paketo Buildpacks?
Paketo Buildpacks are Cloud Native Buildpack (CNB) implementations that transform your application source code into container images. They provide intelligent defaults, security updates, and optimizations specifically designed for Java applications.
Key Benefits for Java Teams:
- No Dockerfile Required: Build containers directly from source code
- Automatic Dependency Management: Handle Maven, Gradle, and JAR files
- Security Scanning: Built-in vulnerability scanning
- Optimized Images: Minimal, secure, and efficient container images
- Build Caching: Faster rebuilds with intelligent caching
- Polyglot Support: Consistent build process across languages
Installation and Setup
1. Install Paketo CLI Tools
Mac with Homebrew:
brew install paketobuildpacks/tap/pack
Linux:
wget https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz tar -xzf pack-v0.32.1-linux.tgz sudo mv pack /usr/local/bin/
Docker (No Installation Required):
docker run -v $(pwd):/workspace -w /workspace paketobuildpacks/builder:base pack build my-app
2. Verify Installation
pack --version pack suggest-builders
Basic Usage with Java Applications
1. Building a Simple Spring Boot Application
Project Structure:
my-spring-app/ ├── pom.xml ├── src/ │ └── main/ │ └── java/ │ └── com/ │ └── example/ │ └── MyApplication.java └── .gitignore
Build Command:
pack build my-spring-app \ --path . \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17
2. Building with Different Builders
# Base builder (recommended for most applications) pack build my-app --builder paketobuildpacks/builder:base # Full builder (includes more buildpacks) pack build my-app --builder paketobuildpacks/builder:full # Tiny builder (minimal image size) pack build my-app --builder paketobuildpacks/builder:tiny
Maven Project Configuration
1. Standard Maven Project
# Build from current directory pack build my-maven-app \ --builder paketobuildpacks/builder:base # Build with specific Java version pack build my-maven-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 # Build from different directory pack build my-maven-app \ --path ./subdirectory/maven-project \ --builder paketobuildpacks/builder:base
2. Maven with Custom Settings
pack build my-maven-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \ --env BP_MAVEN_BUILT_ARTIFACT="target/*.jar"
3. Multi-Module Maven Project
pack build my-multi-module-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_BUILT_MODULE="./my-web-module" \ --env BP_MAVEN_BUILT_ARTIFACT="target/*.jar"
Gradle Project Configuration
1. Standard Gradle Project
# Basic Gradle build pack build my-gradle-app \ --builder paketobuildpacks/builder:base # Gradle with Java 17 pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 # Custom Gradle tasks pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_GRADLE_BUILD_ARGUMENTS="build -x test" \ --env BP_GRADLE_BUILT_ARTIFACT="build/libs/*.jar"
2. Gradle with Wrapper
pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_GRADLE_BUILT_ARTIFACT="build/libs/*.jar" \ --env BP_GRADLE_BUILD_ARGUMENTS="-Dorg.gradle.daemon=false build"
Advanced Configuration
1. Environment Variables Configuration
pack build my-java-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BPL_JVM_HEAD_ROOM=8 \ --env BPL_JVM_LOADED_CLASS_COUNT=35 \ --env BPL_JVM_THREAD_COUNT=50 \ --env SPRING_PROFILES_ACTIVE=production \ --env JAVA_TOOL_OPTIONS="-Dserver.port=8080 -Xmx512m"
2. Custom JVM Configuration
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BPL_JAVA_OPTS="-XX:+UseG1GC -XX:MaxRAMPercentage=75.0" \ --env BPL_DEBUG_ENABLED=true \ --env BPL_DEBUG_PORT=8000 \ --env BPL_JMX_ENABLED=true \ --env BPL_JMX_PORT=1099
3. Resource Configuration
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BPL_JVM_HEAD_ROOM=5 \ --env BPL_JVM_LOADED_CLASS_COUNT=35 \ --env BPL_JVM_THREAD_COUNT=250 \ --env BPL_HEAP_DUMP_PATH="/tmp/heap-dumps"
Spring Boot Specific Configurations
1. Spring Boot Application
pack build my-spring-boot-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env SPRING_PROFILES_ACTIVE=prod \ --env BPL_SPRING_CLOUD_BINDINGS_ENABLED=false
2. Spring Boot with Actuator
pack build my-spring-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,info,metrics \ --env MANAGEMENT_HEALTH_PROBES_ENABLED=true
3. Spring Native (GraalVM)
pack build my-spring-native-app \ --builder paketobuildpacks/builder:base \ --env BP_NATIVE_IMAGE=true \ --env BP_MAVEN_BUILD_ARGUMENTS="-Pnative clean package" \ --env BP_JVM_VERSION=17
Buildpack Configuration Files
1. project.toml Configuration
Create a project.toml file in your project root:
# project.toml
[[build.env]]
name = "BP_JVM_VERSION"
value = "17"
[[build.env]]
name = "BP_MAVEN_BUILD_ARGUMENTS"
value = "-DskipTests clean package"
[[build.env]]
name = "BP_MAVEN_BUILT_ARTIFACT"
value = "target/*.jar"
# Runtime environment variables
[[io.buildpacks.build.metadata]]
name = "SPRING_PROFILES_ACTIVE"
value = "production"
[[io.buildpacks.build.metadata]]
name = "JAVA_OPTS"
value = "-Xmx512m -Xms256m"
# Buildpack requirements
[[build.buildpacks]]
id = "paketo-buildpacks/maven"
version = "7.8.0"
[[build.buildpacks]]
id = "paketo-buildpacks/executable-jar"
version = "6.15.0"
[[build.buildpacks]]
id = "paketo-buildpacks/spring-boot"
version = "6.11.0"
# Buildpack order
[[build.order]]
group = [
{ id = "paketo-buildpacks/maven", version = "7.8.0" },
{ id = "paketo-buildpacks/executable-jar", version = "6.15.0" },
{ id = "paketo-buildpacks/spring-boot", version = "6.11.0" },
{ id = "paketo-buildpacks/dist-zip", version = "5.7.0" }
]
2. Build Configuration with project.toml
pack build my-app \ --builder paketobuildpacks/builder:base \ --descriptor project.toml
Custom Buildpack Stacks
1. Using Different Base Images
# Base stack (Ubuntu-based) pack build my-app --builder paketobuildpacks/builder:base # Full stack (more build tools) pack build my-app --builder paketobuildpacks/builder:full # Tiny stack (distroless, minimal) pack build my-app --builder paketobuildpacks/builder:tiny
2. Custom Stack Configuration
# stack.toml
[buildpack]
id = "my-company/java-buildpack" version = "1.0.0" [[order]] group = [ { id = "paketo-buildpacks/ca-certificates", version = "3.5.0" }, { id = "paketo-buildpacks/bellsoft-liberica", version = "10.1.0" }, { id = "paketo-buildpacks/maven", version = "7.8.0" }, { id = "paketo-buildpacks/executable-jar", version = "6.15.0" }, { id = "paketo-buildpacks/spring-boot", version = "6.11.0" } ]
Security and Optimization
1. Security Scanning
# Build with security scanning pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG # Check for vulnerabilities docker scan my-app # Build with specific CA certificates pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_EMBED_CERTS=true
2. Image Optimization
# Build minimal image pack build my-app \ --builder paketobuildpacks/builder:tiny \ --env BP_JVM_VERSION=17 \ --env BP_JVM_TYPE=JRE # Remove build dependencies pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DEFAULT_PROCESS=web
3. Non-Root User Execution
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LIVE_RELOAD_ENABLED=true \ --user 1000:1000
CI/CD Integration
1. GitHub Actions Workflow
# .github/workflows/paketo-build.yml
name: Build with Paketo Buildpacks
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
name: Build Container Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Install pack CLI
run: |
curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | sudo tar -C /usr/local/bin/ -xz pack
- name: Build with Paketo
run: |
pack build ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
--builder paketobuildpacks/builder:base \
--env BP_JVM_VERSION=17 \
--env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \
--path . \
--verbose
- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
if: github.event_name != 'pull_request'
run: |
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
docker tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Security scan
run: |
docker scan ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
2. GitLab CI Configuration
# .gitlab-ci.yml image: docker:latest services: - docker:dind variables: DOCKER_HOST: tcp://docker:2375 DOCKER_TLS_CERTDIR: "" stages: - build - scan build: stage: build before_script: - apk add --no-cache curl - curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack - mv pack /usr/local/bin/ script: - | pack build $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \ --path . \ --publish only: - main - develop security_scan: stage: scan script: - apk add --no-cache curl - curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack - mv pack /usr/local/bin/ - pack build --pull-policy never my-app-scan \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG - docker scan my-app-scan
3. Jenkins Pipeline
pipeline {
agent any
environment {
IMAGE_NAME = "my-company/my-java-app"
BUILDER = "paketobuildpacks/builder:base"
}
stages {
stage('Build with Paketo') {
steps {
script {
sh '''
curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack
sudo mv pack /usr/local/bin/
pack build ${IMAGE_NAME}:${BUILD_NUMBER} \
--builder ${BUILDER} \
--env BP_JVM_VERSION=17 \
--env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \
--path . \
--verbose
'''
}
}
}
stage('Security Scan') {
steps {
sh '''
docker scan ${IMAGE_NAME}:${BUILD_NUMBER}
'''
}
}
stage('Push to Registry') {
steps {
script {
docker.withRegistry('https://registry.mycompany.com', 'docker-credentials') {
sh """
docker push ${IMAGE_NAME}:${BUILD_NUMBER}
docker tag ${IMAGE_NAME}:${BUILD_NUMBER} ${IMAGE_NAME}:latest
docker push ${IMAGE_NAME}:latest
"""
}
}
}
}
}
}
Troubleshooting and Debugging
1. Debug Build Process
# Enable verbose logging pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG \ --verbose # Inspect built image pack inspect-image my-app # Check buildpack layers dive my-app
2. Analyze Buildpack Detection
# Check which buildpacks would be used pack detect --path . # List available buildpacks pack builder inspect paketobuildpacks/builder:base # Build with specific buildpacks pack build my-app \ --builder paketobuildpacks/builder:base \ --buildpack paketo-buildpacks/maven \ --buildpack paketo-buildpacks/executable-jar
3. Common Issues and Solutions
# Force rebuild without cache pack build my-app --clear-cache --builder paketobuildpacks/builder:base # Build with custom network (for corporate environments) pack build my-app --network host --builder paketobuildpacks/builder:base # Set memory limits for build pack build my-app --builder paketobuildpacks/builder:base --env BP_JVM_BUILD_ARGUMENTS="-Xmx2g"
Best Practices
1. Image Size Optimization
# Use JRE instead of JDK for runtime pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_TYPE=JRE # Use tiny builder for minimal images pack build my-app \ --builder paketobuildpacks/builder:tiny \ --env BP_JVM_VERSION=17 # Remove development dependencies pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DEFAULT_PROCESS=web
2. Security Hardening
# Build with non-root user pack build my-app \ --builder paketobuildpacks/builder:base \ --user 1000:1000 # Enable security scanning pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_SECURITY_SCANNER_ENABLED=true # Use specific Java version for security patches pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17.0.8
3. Performance Optimization
# Enable build caching pack build my-app \ --builder paketobuildpacks/builder:base \ --volume $(pwd)/pack-cache:/tmp/cache # Use layer caching pack build my-app \ --builder paketobuildpacks/builder:base \ --cache-image my-registry/cache-image:latest # Parallel dependency download pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DOWNLOAD_THREADS=5
Conclusion
Paketo Buildpacks provide Java teams with a robust, secure, and efficient way to build container images:
- Simplified Workflow: No Dockerfile maintenance required
- Security First: Built-in vulnerability scanning and updates
- Optimized Images: Production-ready images with best practices
- Flexible Configuration: Extensive environment variable support
- CI/CD Ready: Easy integration with existing pipelines
By adopting Paketo Buildpacks, Java teams can focus on application development while ensuring consistent, secure, and optimized container builds across all environments.
x
Article
Paketo Buildpacks provide a modern, declarative approach to building production-ready container images for Java applications without writing Dockerfiles. They automatically detect your application type, resolve dependencies, and create optimized container images following cloud-native best practices.
What are Paketo Buildpacks?
Paketo Buildpacks are Cloud Native Buildpack (CNB) implementations that transform your application source code into container images. They provide intelligent defaults, security updates, and optimizations specifically designed for Java applications.
Key Benefits for Java Teams:
- No Dockerfile Required: Build containers directly from source code
- Automatic Dependency Management: Handle Maven, Gradle, and JAR files
- Security Scanning: Built-in vulnerability scanning
- Optimized Images: Minimal, secure, and efficient container images
- Build Caching: Faster rebuilds with intelligent caching
- Polyglot Support: Consistent build process across languages
Installation and Setup
1. Install Paketo CLI Tools
Mac with Homebrew:
brew install paketobuildpacks/tap/pack
Linux:
wget https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz tar -xzf pack-v0.32.1-linux.tgz sudo mv pack /usr/local/bin/
Docker (No Installation Required):
docker run -v $(pwd):/workspace -w /workspace paketobuildpacks/builder:base pack build my-app
2. Verify Installation
pack --version pack suggest-builders
Basic Usage with Java Applications
1. Building a Simple Spring Boot Application
Project Structure:
my-spring-app/ ├── pom.xml ├── src/ │ └── main/ │ └── java/ │ └── com/ │ └── example/ │ └── MyApplication.java └── .gitignore
Build Command:
pack build my-spring-app \ --path . \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17
2. Building with Different Builders
# Base builder (recommended for most applications) pack build my-app --builder paketobuildpacks/builder:base # Full builder (includes more buildpacks) pack build my-app --builder paketobuildpacks/builder:full # Tiny builder (minimal image size) pack build my-app --builder paketobuildpacks/builder:tiny
Maven Project Configuration
1. Standard Maven Project
# Build from current directory pack build my-maven-app \ --builder paketobuildpacks/builder:base # Build with specific Java version pack build my-maven-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 # Build from different directory pack build my-maven-app \ --path ./subdirectory/maven-project \ --builder paketobuildpacks/builder:base
2. Maven with Custom Settings
pack build my-maven-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \ --env BP_MAVEN_BUILT_ARTIFACT="target/*.jar"
3. Multi-Module Maven Project
pack build my-multi-module-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_BUILT_MODULE="./my-web-module" \ --env BP_MAVEN_BUILT_ARTIFACT="target/*.jar"
Gradle Project Configuration
1. Standard Gradle Project
# Basic Gradle build pack build my-gradle-app \ --builder paketobuildpacks/builder:base # Gradle with Java 17 pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 # Custom Gradle tasks pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_GRADLE_BUILD_ARGUMENTS="build -x test" \ --env BP_GRADLE_BUILT_ARTIFACT="build/libs/*.jar"
2. Gradle with Wrapper
pack build my-gradle-app \ --builder paketobuildpacks/builder:base \ --env BP_GRADLE_BUILT_ARTIFACT="build/libs/*.jar" \ --env BP_GRADLE_BUILD_ARGUMENTS="-Dorg.gradle.daemon=false build"
Advanced Configuration
1. Environment Variables Configuration
pack build my-java-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BPL_JVM_HEAD_ROOM=8 \ --env BPL_JVM_LOADED_CLASS_COUNT=35 \ --env BPL_JVM_THREAD_COUNT=50 \ --env SPRING_PROFILES_ACTIVE=production \ --env JAVA_TOOL_OPTIONS="-Dserver.port=8080 -Xmx512m"
2. Custom JVM Configuration
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BPL_JAVA_OPTS="-XX:+UseG1GC -XX:MaxRAMPercentage=75.0" \ --env BPL_DEBUG_ENABLED=true \ --env BPL_DEBUG_PORT=8000 \ --env BPL_JMX_ENABLED=true \ --env BPL_JMX_PORT=1099
3. Resource Configuration
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BPL_JVM_HEAD_ROOM=5 \ --env BPL_JVM_LOADED_CLASS_COUNT=35 \ --env BPL_JVM_THREAD_COUNT=250 \ --env BPL_HEAP_DUMP_PATH="/tmp/heap-dumps"
Spring Boot Specific Configurations
1. Spring Boot Application
pack build my-spring-boot-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env SPRING_PROFILES_ACTIVE=prod \ --env BPL_SPRING_CLOUD_BINDINGS_ENABLED=false
2. Spring Boot with Actuator
pack build my-spring-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,info,metrics \ --env MANAGEMENT_HEALTH_PROBES_ENABLED=true
3. Spring Native (GraalVM)
pack build my-spring-native-app \ --builder paketobuildpacks/builder:base \ --env BP_NATIVE_IMAGE=true \ --env BP_MAVEN_BUILD_ARGUMENTS="-Pnative clean package" \ --env BP_JVM_VERSION=17
Buildpack Configuration Files
1. project.toml Configuration
Create a project.toml file in your project root:
# project.toml
[[build.env]]
name = "BP_JVM_VERSION"
value = "17"
[[build.env]]
name = "BP_MAVEN_BUILD_ARGUMENTS"
value = "-DskipTests clean package"
[[build.env]]
name = "BP_MAVEN_BUILT_ARTIFACT"
value = "target/*.jar"
# Runtime environment variables
[[io.buildpacks.build.metadata]]
name = "SPRING_PROFILES_ACTIVE"
value = "production"
[[io.buildpacks.build.metadata]]
name = "JAVA_OPTS"
value = "-Xmx512m -Xms256m"
# Buildpack requirements
[[build.buildpacks]]
id = "paketo-buildpacks/maven"
version = "7.8.0"
[[build.buildpacks]]
id = "paketo-buildpacks/executable-jar"
version = "6.15.0"
[[build.buildpacks]]
id = "paketo-buildpacks/spring-boot"
version = "6.11.0"
# Buildpack order
[[build.order]]
group = [
{ id = "paketo-buildpacks/maven", version = "7.8.0" },
{ id = "paketo-buildpacks/executable-jar", version = "6.15.0" },
{ id = "paketo-buildpacks/spring-boot", version = "6.11.0" },
{ id = "paketo-buildpacks/dist-zip", version = "5.7.0" }
]
2. Build Configuration with project.toml
pack build my-app \ --builder paketobuildpacks/builder:base \ --descriptor project.toml
Custom Buildpack Stacks
1. Using Different Base Images
# Base stack (Ubuntu-based) pack build my-app --builder paketobuildpacks/builder:base # Full stack (more build tools) pack build my-app --builder paketobuildpacks/builder:full # Tiny stack (distroless, minimal) pack build my-app --builder paketobuildpacks/builder:tiny
2. Custom Stack Configuration
# stack.toml
[buildpack]
id = "my-company/java-buildpack" version = "1.0.0" [[order]] group = [ { id = "paketo-buildpacks/ca-certificates", version = "3.5.0" }, { id = "paketo-buildpacks/bellsoft-liberica", version = "10.1.0" }, { id = "paketo-buildpacks/maven", version = "7.8.0" }, { id = "paketo-buildpacks/executable-jar", version = "6.15.0" }, { id = "paketo-buildpacks/spring-boot", version = "6.11.0" } ]
Security and Optimization
1. Security Scanning
# Build with security scanning pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG # Check for vulnerabilities docker scan my-app # Build with specific CA certificates pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_EMBED_CERTS=true
2. Image Optimization
# Build minimal image pack build my-app \ --builder paketobuildpacks/builder:tiny \ --env BP_JVM_VERSION=17 \ --env BP_JVM_TYPE=JRE # Remove build dependencies pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DEFAULT_PROCESS=web
3. Non-Root User Execution
pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LIVE_RELOAD_ENABLED=true \ --user 1000:1000
CI/CD Integration
1. GitHub Actions Workflow
# .github/workflows/paketo-build.yml
name: Build with Paketo Buildpacks
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
name: Build Container Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Install pack CLI
run: |
curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | sudo tar -C /usr/local/bin/ -xz pack
- name: Build with Paketo
run: |
pack build ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
--builder paketobuildpacks/builder:base \
--env BP_JVM_VERSION=17 \
--env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \
--path . \
--verbose
- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
if: github.event_name != 'pull_request'
run: |
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
docker tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Security scan
run: |
docker scan ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
2. GitLab CI Configuration
# .gitlab-ci.yml image: docker:latest services: - docker:dind variables: DOCKER_HOST: tcp://docker:2375 DOCKER_TLS_CERTDIR: "" stages: - build - scan build: stage: build before_script: - apk add --no-cache curl - curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack - mv pack /usr/local/bin/ script: - | pack build $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17 \ --env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \ --path . \ --publish only: - main - develop security_scan: stage: scan script: - apk add --no-cache curl - curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack - mv pack /usr/local/bin/ - pack build --pull-policy never my-app-scan \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG - docker scan my-app-scan
3. Jenkins Pipeline
pipeline {
agent any
environment {
IMAGE_NAME = "my-company/my-java-app"
BUILDER = "paketobuildpacks/builder:base"
}
stages {
stage('Build with Paketo') {
steps {
script {
sh '''
curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -xz pack
sudo mv pack /usr/local/bin/
pack build ${IMAGE_NAME}:${BUILD_NUMBER} \
--builder ${BUILDER} \
--env BP_JVM_VERSION=17 \
--env BP_MAVEN_BUILD_ARGUMENTS="-DskipTests clean package" \
--path . \
--verbose
'''
}
}
}
stage('Security Scan') {
steps {
sh '''
docker scan ${IMAGE_NAME}:${BUILD_NUMBER}
'''
}
}
stage('Push to Registry') {
steps {
script {
docker.withRegistry('https://registry.mycompany.com', 'docker-credentials') {
sh """
docker push ${IMAGE_NAME}:${BUILD_NUMBER}
docker tag ${IMAGE_NAME}:${BUILD_NUMBER} ${IMAGE_NAME}:latest
docker push ${IMAGE_NAME}:latest
"""
}
}
}
}
}
}
Troubleshooting and Debugging
1. Debug Build Process
# Enable verbose logging pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_LOG_LEVEL=DEBUG \ --verbose # Inspect built image pack inspect-image my-app # Check buildpack layers dive my-app
2. Analyze Buildpack Detection
# Check which buildpacks would be used pack detect --path . # List available buildpacks pack builder inspect paketobuildpacks/builder:base # Build with specific buildpacks pack build my-app \ --builder paketobuildpacks/builder:base \ --buildpack paketo-buildpacks/maven \ --buildpack paketo-buildpacks/executable-jar
3. Common Issues and Solutions
# Force rebuild without cache pack build my-app --clear-cache --builder paketobuildpacks/builder:base # Build with custom network (for corporate environments) pack build my-app --network host --builder paketobuildpacks/builder:base # Set memory limits for build pack build my-app --builder paketobuildpacks/builder:base --env BP_JVM_BUILD_ARGUMENTS="-Xmx2g"
Best Practices
1. Image Size Optimization
# Use JRE instead of JDK for runtime pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_TYPE=JRE # Use tiny builder for minimal images pack build my-app \ --builder paketobuildpacks/builder:tiny \ --env BP_JVM_VERSION=17 # Remove development dependencies pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DEFAULT_PROCESS=web
2. Security Hardening
# Build with non-root user pack build my-app \ --builder paketobuildpacks/builder:base \ --user 1000:1000 # Enable security scanning pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_SECURITY_SCANNER_ENABLED=true # Use specific Java version for security patches pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_JVM_VERSION=17.0.8
3. Performance Optimization
# Enable build caching pack build my-app \ --builder paketobuildpacks/builder:base \ --volume $(pwd)/pack-cache:/tmp/cache # Use layer caching pack build my-app \ --builder paketobuildpacks/builder:base \ --cache-image my-registry/cache-image:latest # Parallel dependency download pack build my-app \ --builder paketobuildpacks/builder:base \ --env BP_MAVEN_DOWNLOAD_THREADS=5
Conclusion
Paketo Buildpacks provide Java teams with a robust, secure, and efficient way to build container images:
- Simplified Workflow: No Dockerfile maintenance required
- Security First: Built-in vulnerability scanning and updates
- Optimized Images: Production-ready images with best practices
- Flexible Configuration: Extensive environment variable support
- CI/CD Ready: Easy integration with existing pipelines
By adopting Paketo Buildpacks, Java teams can focus on application development while ensuring consistent, secure, and optimized container builds across all environments.