For convenience, one of the deployment options in BAMOE Canvas allows the user to input a custom image and a custom command to start the application once the upload is complete.

BAMOE Canvas expects a few things from a custom image to guarantee it can upload the project assets and manage the deployment on the Kubernetes/OpenShift cluster.

Requirements:

  1. Have the Dev Deployment Upload Service binary installed and available globally, as BAMOE Canvas will override the default command from your image with dev-deployment-upload-service && <CUSTOM_COMMAND> (<CUSTOM_COMMAND> is defined in the UI when deploying the image);

  2. The image must expose port 8080, and all services running on the container should listen to this port. This includes the dev-deployment-upload-service, which can be configured by setting the DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT environment variable to 8080;

  3. After BAMOE Canvas uploads the assets to the dev-deployment-upload-service listening inside your image, and the service finishes unzipping and placing the files in the configured directory, it’s expected that an application will start and provide an endpoint /q/health that responds with HTTP 200 so that BAMOE Canvas can acknowledge that the application started successfully and is running;

Example 1: Using the Canvas Dev Deployment Base image

The quay.io/bamoe/canvas-dev-deployment-base:9.1.0-ibm-0001 image is used as a base since it already has the dev-deployment-upload-service pre-configured.

Containerfile

# Set the base image with Java 17, Maven, and the dev-deployment-upload-service.
FROM quay.io/bamoe/canvas-dev-deployment-base:9.1.0-ibm-0001

# Start as root to get elevated access.
USER root

# Configure the dev-deployment-upload-service:
# Our extraction directory is /src/main/resources inside our Quarkus app, but it may differ for your application.
# This is the path where all files from your BAMOE Canvas project (including .dmn, .bpmn, etc) will be extracted to after upload.
ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_EXTRACT_TO_DIR=$HOME_PATH/app/src/main/resources
ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT=8080

# Copy your Quarkus app folder with everything needed to run a Quarkus app with .dmn and .bpmn resources,
# setting the permissions/ownership for the target user.
COPY --chown=$USER_ID:$USER_ID ./my-quarkus-app $HOME_PATH/app/

# Expose port 8080
EXPOSE 8080

# Set to a user different than root (in this case, user ID 185, coming from our base image).
USER $USER_ID

# Set the entrypoint to run bash.
ENTRYPOINT ["/bin/bash", "-c"]

# The CMD directive is unnecessary since BAMOE Canvas will overwrite it.

Example 2: Using an OpenJDK base image

Using the icr.io/appcafe/ibm-semeru-runtimes:open-17-jdk-ubi-minimal image as a base, create a Dev Deployment image that follows all the requirements listed above and results in a Quarkus app running with the project files uploaded by BAMOE Canvas.

Containerfile

# Set the base image with Java 17 and Maven.
FROM icr.io/appcafe/ibm-semeru-runtimes:open-17-jdk-ubi-minimal

# Arguments and environment variables to define our user and home path.
# Obs.: This can vary according to your base image.
ARG USER_ID_ARG=185
ARG HOME_PATH_ARG=$HOME
ENV USER_ID=${USER_ID_ARG}
ENV HOME_PATH=${HOME_PATH_ARG}

# Start as root to install all required dependencies.
USER root

# Configure the dev-deployment-upload-service:
# Our extraction directory is /src/main/resources inside our Quarkus app, but it may differ for your application.
# This is the path where all files from your BAMOE Canvas project (including .dmn, .bpmn, etc) will be extracted to after upload.
ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_EXTRACT_TO_DIR=$HOME_PATH/app/src/main/resources
ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT=8080

# Install `tar` and `gzip` packages, as they are required by the dev-deployment-upload-service to unzip the uploaded files.
RUN microdnf --disableplugin=subscription-manager install -y tar gzip \
 && microdnf --disableplugin=subscription-manager clean all

# Create the user home, tmp, and .m2 paths to be used by our application.
# Setting the permission to 777 is important so users can access and modify these files during runtime.
RUN mkdir -p -m 777 $HOME_PATH/app \
 && mkdir -p -m 777 /tmp/app \
 && mkdir -p -m 777 /.m2

# Copy the dev-deployment-upload-service binary to the /usr/local/bin directory, making it globally available.
# NOTE: In this base image /usr/local/bin is included in the PATH environment variable,
# if you're using a different one, make sure the binary is globally accessible.
COPY dev-deployment-upload-service /usr/local/bin

# Another round of changing permissions and ownership of directories.
# This is important because our Quarkus app will make changes to files during runtime.
RUN chgrp -R 0 $HOME_PATH/app && \
 chmod -R 777 $HOME_PATH/app && \
 chgrp -R 0 /.m2 && \
 chmod -R 777 /.m2

# Change the work directory to our app path.
WORKDIR $HOME_PATH/app/

# Copy your Quarkus app folder with everything needed to run a Quarkus app with .dmn and .bpmn resources,
# setting the permissions/ownership for the target user.
COPY --chown=$USER_ID:$USER_ID ./my-quarkus-app $HOME_PATH/app/

# Expose port 8080
EXPOSE 8080

# Set to a user different than root (in this case, user ID 185, but it may vary depending on your base image).
USER $USER_ID

# Set the entrypoint to run bash.
ENTRYPOINT ["/bin/bash", "-c"]

# The CMD directive is unnecessary since BAMOE Canvas will overwrite it.

All that is needed to do is build and publish the image.

Using the custom image on BAMOE Canvas

For the following steps, assume the image tagged and pushed to quay.io/myUserName/myDevDeploymentImage:latest.

When creating a Dev Deployment on BAMOE Canvas, this modal will display:

deployment option kogito quarkus blank app
Figure 1. Deploy modal

By default, it uses the pre-configured Kogito Quarkus Blank App option. To use the custom image, open the dropdown and select Custom Image.

deployment option custom image
Figure 2. Custom Image deployment option

Notice the Docker Image parameter; it must be changed to the custom image tag created (quay.io/myUserName/myDevDeploymentImage:latest in this example).

Also, notice the Command parameter; Its value is the command executed inside the $HOME_PATH/app directory after the upload step is finished. In other words, after the token interpolation is finished, the resulting command executed on the container will be dev-deployment-upload-service && ./mvnw quarkus:dev.

This image does not provide the Maven binary globally, so it is not possible to call mvn directly. Instead, the image provides a Maven wrapper that can be called with ./mvnw from the $HOME_PATH directory.

Important

When deploying to a local Kubernetes cluster configured via the Kubernetes Cluster Wizard from BAMOE Canvas, the Command will need a few more parameters for a Quarkus app:

./mvnw quarkus:dev -Dquarkus.http.non-application-root-path=/${{ devDeployment.uniqueName }}/q -Dquarkus.http.root-path=/${{ devDeployment.uniqueName }}"

When deploying to an OpenShift cluster, ./mvnw quarkus:dev will work without any flags.

This is because the Ingress controller is configured to use sub-paths for each Dev Deployment instead of new subdomains on the Kubernetes cluster, verify that the Quarkus app conforms to these sub-paths.