5

Does anyone has an idea how to build quarkus native image on cloudbuild? I use following command to do so:

- name: maven:3-jdk-11
    entrypoint: mvn
    args: ["package", "-Dmaven.test.skip=true", "-Pnative", "-Dquarkus.native.container-build=true", "-Dquarkus.container-image.build=true"]

Locally everything works fine, but when I try to do it on Google Cloud it throws an error:

[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:1.12.2.Final:build (default) on project fishki: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]     [error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#build threw an exception: java.lang.IllegalStateException: No container runtime was found to run the native image builder
[ERROR]     at io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner.detectContainerRuntime(NativeImageBuildContainerRunner.java:114)

My idea is to try to provide the container runtime to run the native image builder, but I have no idea how to do it.

I will appreciate any help, thanks!

EDIT:

I use following cloudbuild.yaml

steps:
  - name: maven:3-jdk-11
    entrypoint: mvn
    args: ["quarkus:add-extension", "-Dextensions=container-image-docker"]
  - name: docker:latest
  - name: maven:3-jdk-11
    entrypoint: mvn
    args: ["package", "-Pnative", "-Dmaven.test.skip=true", "-Dquarkus.container-image.build=true", "-Dquarkus.native.container-build=true", "-Dquarkus.native.container-runtime=docker"]
  - name: 'gcr.io/cloud-builders/docker'
    args: [ 'build', '-t', 'gcr.io/XXX-XX-XXX/XX-XXX', '.' ]
  - name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/XXXX/XXX-XXXX"]
  - name: "gcr.io/cloud-builders/gke-deploy"
    args:
      - run
      - --filename=./deployment.yaml
      - --image=gcr.io/XXX/XXX:latest
      - --location=europe-west1-b
      - --cluster=XX-XXX-XXX-1

Now I have a new problem - when I try to install docker container runtime, I get the following error:

[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:1.12.2.Final:build (default) on project fishki: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]     [error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#build threw an exception: java.lang.RuntimeException: Failed to pull builder image quay.io/quarkus/ubi-quarkus-native-image:21.0.0-java11
Ksz
  • 53
  • 1
  • 5

3 Answers3

2

I was struggling with this for a while, but the info in the question you asked helped me a lot, so thank you for the ideas which lead me to resolve this issue.

The way I ended up doing it was to build a custom build image like so (Dockerfile):

FROM maven:3-jdk-11
run apt-get update
run apt-get install docker.io -y
run docker --version

You can find my build image here (note: mine works with gradle, not maven): https://hub.docker.com/repository/docker/lackrobin/quarkus-gradle-build-image

Push this image to the gcr, or any other registry that you can access from google cloud build.

In the cloudbuild.yaml file the following configuration should do the trick:

steps:
  - name: gcr.io/[link to the builder image above]
    args:
      - addExtension
      - '--extensions=container-image-docker'
      - build
      - '-Dquarkus.package.type=native'
      - '-Dquarkus.native.native-image-xmx=16g'
      - '-Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m'
    entrypoint: ./gradlew
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - '-t'
      - gcr.io/[project name]/[image name]
      - '-f'
      - src/main/docker/Dockerfile.native
      - .
images:
timeout: 2000s
  - gcr.io/gcr.io/[project name]/[image name]
options:
  machineType: E2_HIGHCPU_32

quarkus, or GraalVM uses a lot of resources to build. I had to use a vm with more resources for the build. The command machineType: E2_HIGHCPU_32 under options is responsible for that.

GD21
  • 223
  • 2
  • 10
1

That's how I did it.

I locally prepared this Dockerfile:

## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi-quarkus-native-image:22.2-java17 AS build
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
USER quarkus
WORKDIR /code
RUN ls -latr ./mvnw
RUN chmod u+x ./mvnw
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
RUN ls -latr ./mvnw
COPY src /code/src
RUN ./mvnw package -Pnative -DskipTests -Dquarkus.native.native-image-xmx=7G

## Stage 2 : create the docker final image
FROM quay.io/quarkus/quarkus-micro-image:1.0
WORKDIR /work/
COPY --from=build /code/target/*-runner /work/application

# set up permissions for user `1001`
RUN chmod 775 /work /work/application \
  && chown -R 1001 /work \
  && chmod -R "g+rwX" /work \
  && chown -R 1001:root /work

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

then this is the cloudbuild.yaml:

# Build for Graal VM tend to take some time.
timeout: '1800s'

steps:
  - name: 'ubuntu'
    script: |
      #!/bin/bash
      echo "=== pwd ==="
      pwd
      echo "=== ls ==="
      ls -latr
      echo "=== ls dockerfiles ==="
      ls -latr src/main/docker      
      echo "=== env ==="
      env

  # Build the native image
  - name: 'gcr.io/cloud-builders/docker'
    args: [ 'build', '--file', 'src/main/docker/Dockerfile', '--tag', '$_COMPLETE_IMAGE_NAME:develop', '.' ]
    # Build for Graal VM tend to take some time.
    timeout: '1800s'

  # Docker Push
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - push
      - '$_COMPLETE_IMAGE_NAME:develop'

options:
  machineType: 'E2_HIGHCPU_8'

# Default variables
# https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values
substitutions:
  _DOCKER_IMAGENAME: <the-image-name>
  _DOCKER_REGISTRY: <the-reistry-name>
  _SERVICE_REGION: europe-west1
  _ARTIFACT_REPO: ${_SERVICE_REGION}-docker.pkg.dev/${PROJECT_ID}/${_DOCKER_REGISTRY}
  _COMPLETE_IMAGE_NAME: ${_ARTIFACT_REPO}/${_DOCKER_IMAGENAME}

danidemi
  • 4,404
  • 4
  • 34
  • 40
0

For each build step, Cloud Build executes a docker container as an instance of docker run. What your app requires is the container runtime itself. Therefore you cannot build your container using pre-built Maven builder as the image doesn't have the requirements needed by your app. By looking at Quarkus docs, you can see that Docker runtime is required to build a native executable.

Update: One solution is by creating your own custom builder where you can set the environment with all the requirements (JDK, Maven, Docker, etc.), and then using it on your build step instead of using a pre-made builder.

See this instructions how to build containers with a Dockerfile.

As additional reference, here's Quarkus quickstart guide.

Donnald Cucharo
  • 3,866
  • 1
  • 10
  • 17
  • 1
    I have seen these instructions, but they don't provide an answer for my problem (or I miss something). Thanks for help. – Ksz Mar 16 '21 at 20:45
  • @Ksz please see if my updated answer can help you to the right direction – Donnald Cucharo Mar 16 '21 at 23:50
  • I feel like I am one step closer to succed, but I have a new problem. Seems like I cannot download docker-builder from inside a cloudbuild environment. – Ksz Mar 17 '21 at 22:44