APIs have become the lifeblood of modern applications, and managing them effectively is crucial. WSO2 API Manager (APIM) emerges as a powerful tool for creating, publishing, and securing your APIs. But how do you leverage its potential in a containerized environment like OpenShift?
Some companies have policies that require using RedHat UBI-minimal as the base image for creating new images. What are its pros and cons? How to change standard wso2 APIM docker files to compatible with UBI-minimal?
This blog explores the process of building and deploying WSO2 APIM images in OpenShift using the UBI-minimal base image, enabling you to manage your APIs with agility and precision.
What is RedHat UBI-minimal
RedHat UBI-minimal is a lean container base image focused on minimal size and security. Built by RedHat, it’s freely redistributable but support is limited to core functionality. It uses microdnf for package management and is ideal for smaller deployments where size and security are top priorities.
Whether or not it’s “better” to use Red Hat UBI-minimal as a base image for deploying WSO2 APIM in OpenShift depends on your specific needs and priorities. Here’s a breakdown of the pros and cons to help you decide:
- Pros of using UBI-minimal:
- Smaller Image Size: UBI-minimal is a stripped-down image with only essential components, resulting in a smaller footprint and faster deployment times.
- Security Focus: Red Hat maintains and updates UBI-minimal with security patches, potentially enhancing the overall security posture of your deployment.
- Freely Redistributable: You can freely share and reuse UBI-minimal images without licensing restrictions, which might be important for open-source projects or collaborative environments.
- Cons of using UBI-minimal:
- Limited Functionality: As a minimal image, UBI-minimal might lack functionalities that WSO2 APIM requires, forcing you to install additional packages during deployment.
- Package Management: While UBI-minimal uses microdnf, a lightweight package manager, it might differ from your preferred management tools, potentially causing additional configuration steps.
- Support: Red Hat only supports Red Hat technologies within a subscription. For wider support beyond core functionality, you might need to explore alternative solutions.
Based on the benefits of UBI-minimal and organizational policies, you may need to use it as your base image and create your own Dockerfile based on RedHat UBI-minimal.
General WSO2 APIM dockerfile
In this section, a docker file sample is shown. You can customize it or add any libraries or apps you need. In “UBI-minimal” you can use “microdnf” for install any required packages. Next, you need to download WSO2 APIM 4.3 or any version you require. You can either download it from your organization’s repository manager directly during the build process, using the sample code provided to download it from your Nexus repository with credentials parameters on line 21, or you can copy it from your local directory. You can find this sample in line 22 that is commented.
Delete all installed packages at the end to free up unused space.
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
ARG WSO2_SERVER_NAME=wso2am
ARG WSO2_SERVER_VERSION
ARG WSO2_PATCH_LEVEL
ARG NEXUS_USERNAME
ARG NEXUS_PASSWORD
ARG WSO2_SERVER_DIST_URL
ARG WSO2_FULL_NAME=${WSO2_SERVER_VERSION}.${WSO2_PATCH_LEVEL}
ARG WSO2_BIN_NAME=apim-${WSO2_FULL_NAME}.zip
ARG APP_BASE_DIR=/opt
ARG WSO2_DIR_NAME=${WSO2_SERVER_NAME}-${WSO2_SERVER_VERSION}
ARG WSO2_SERVER_HOME=${APP_BASE_DIR}/${WSO2_DIR_NAME}
ARG JAVA_HOME=/opt/jre
ARG JAVA_CACERTS=${JAVA_HOME}/lib/security/cacerts
# destination WSO2 JKS stores
ARG WSO2_CLIENT_TRUSTSTORE_JKS=${WSO2_SERVER_HOME}/repository/resources/security/client-truststore.jks
LABEL maintainer="WSO2 Docker For RHEL <Afarin>" \
com.wso2.docker.source="https://github.com/wso2/docker-apim"
# Install required packages for unpacking WSO2 sourcen
RUN microdnf install --nodocs -y --setopt install_weak_deps=0 unzip findutils \
&& microdnf clean all
# download from nexus or copy WSO2 binary from local file system
RUN curl -u ${NEXUS_USERNAME}:${NEXUS_PASSWORD} -o ${APP_BASE_DIR}/${WSO2_BIN_NAME} ${WSO2_SERVER_DIST_URL}
# COPY --chown=root:root local/wso2_APIM_4.3.0.zip ${APP_BASE_DIR}/${WSO2_BIN_NAME}
# This Dockerfile command creates necessary directories, sets permissions, unzips wso2 zipfiles,
# and copies specific directories to the target location.
RUN mkdir -p \
${WSO2_SERVER_HOME} && \
chown -R root:root ${WSO2_SERVER_HOME} && \
unzip -d ${APP_BASE_DIR} ${APP_BASE_DIR}/${WSO2_BIN_NAME} && \
rm -rf ${WSO2_SERVER_HOME}/dbscripts && \
find ${WSO2_SERVER_HOME} -type f -exec chmod "u=rw,g=rw,o=rw" {} + && \
find ${WSO2_SERVER_HOME} -type d -exec chmod "u=rwx,g=rwx,o=rwx" {} + && \
find ${WSO2_SERVER_HOME} -name "*.sh" -type f -exec chmod "u+x,g+x" {} +
COPY --from=jenkins/jenkins:rhel-ubi9-jdk21 --chown=root:root /opt/java/openjdk/ ${JAVA_HOME}
COPY --chown=root:root local/docker-entrypoint.sh ${WSO2_SERVER_HOME}
RUN ${JAVA_HOME}/bin/keytool -importkeystore -srckeystore ${JAVA_CACERTS} -destkeystore ${WSO2_CLIENT_TRUSTSTORE_JKS} -srcstorepass changeit -deststorepass wso2carbon -v; exit 0
### Delete package manager stuff
RUN microdnf remove -y unzip findutils \
&& microdnf clean all
RUN rm -fr /var/cache/* /var/lib/dnf /var/lib/rpm /var/lib/rpm-state /etc/yum.repos.d /etc/dnf
WORKDIR ${WSO2_SERVER_HOME}
ENV WORKING_DIRECTORY=${WSO2_SERVER_HOME} \
WSO2_SERVER_HOME=${WSO2_SERVER_HOME} \
JAVA_HOME=${JAVA_HOME} \
WSO2_APIM_VERSION=${WSO2_FULL_NAME}
ENTRYPOINT ["${WSO2_SERVER_HOME}/docker-entrypoint.sh"]
EXPOSE 5672 8672 8280 8243 9099 9443 9611 9711 9763 9999 11111
Optimized WSO2 APIM based on profile
If you plan to install WSO2 APIM in a distributed manner, it is better to have separate images based on profiles. As you know, you can separate Gateway from Control plane then you have 2 components.
Even you can separate Gateway and Traffic-manager and then you have 3 components. You can follow this link to setup distributed environment, but it is out of this blog topic.
By running the code below , you can optimize your APIM for a specific profile.
sh <API-M_HOME>/bin/profileSetup.sh -Dprofile=<preferred-profile>
The code below demonstrates a way to create an optimized and reduces version of WSO2 APIM for each profile.
ARG WSO2_SERVER_NAME=wso2am
ARG WSO2_SERVER_VERSION
ARG WSO2_PATCH_LEVEL
ARG WSO2_PROFILE
ARG NEXUS_USERNAME
ARG NEXUS_PASSWORD
ARG WSO2_SERVER_DIST_URL
ARG WSO2_FULL_NAME=${WSO2_SERVER_VERSION}.${WSO2_PATCH_LEVEL}
ARG WSO2_BIN_NAME=apim-${WSO2_FULL_NAME}.zip
ARG APP_BASE_DIR=/opt
ARG WSO2_DIR_NAME=${WSO2_SERVER_NAME}-${WSO2_SERVER_VERSION}
ARG WSO2_SERVER_HOME=${APP_BASE_DIR}/${WSO2_DIR_NAME}
###
# Setup the build image.
#
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest as builder
ARG WSO2_SERVER_NAME
ARG WSO2_SERVER_VERSION
ARG WSO2_PATCH_LEVEL
ARG WSO2_PROFILE
ARG WSO2_FULL_NAME
ARG WSO2_BIN_NAME
ARG APP_BASE_DIR
ARG WSO2_DIR_NAME
ARG WSO2_SERVER_HOME
ARG WSO2_SERVER_DIST_URL
ARG WSO2_LIB_DIR=${WSO2_SERVER_HOME}/repository/components/lib
ARG WSO2_DROPINS_DIR=${WSO2_SERVER_HOME}/repository/components/dropins
LABEL maintainer="WSO2 Docker For RHEL <Afarin>" \
com.wso2.docker.source="https://github.com/wso2/docker-apim"
LABEL WSO2-APIM-VERSION=${WSO2_FULL_NAME}
# Nexus configs for downloading binaries and plugins
ARG NEXUS_USERNAME
ARG NEXUS_PASSWORD
ARG NEXUS_REPO_URL
# Install required packages for unpacking WSO2 sourcen
RUN microdnf install --nodocs -y --setopt install_weak_deps=0 unzip findutils \
&& microdnf clean all
# download WSO2 binary
RUN curl -u ${NEXUS_USERNAME}:${NEXUS_PASSWORD} -o ${APP_BASE_DIR}/${WSO2_BIN_NAME} ${WSO2_SERVER_DIST_URL}
# COPY --chown=root:root local/wso2_APIM_4.3.0.zip ${APP_BASE_DIR}/${WSO2_BIN_NAME}
# This Dockerfile command creates necessary directories, sets permissions, unzips wso2 zipfiles,
# and copies specific directories to the target location.
RUN mkdir -p \
${WSO2_SERVER_HOME} && \
chown -R root:root ${WSO2_SERVER_HOME} && \
unzip -d ${APP_BASE_DIR} ${APP_BASE_DIR}/${WSO2_BIN_NAME} && \
rm -rf ${WSO2_SERVER_HOME}/dbscripts && \
find ${WSO2_SERVER_HOME} -type f -exec chmod "u=rw,g=rw,o=rw" {} + && \
find ${WSO2_SERVER_HOME} -type d -exec chmod "u=rwx,g=rwx,o=rwx" {} + && \
find ${WSO2_SERVER_HOME} -name "*.sh" -type f -exec chmod "u+x,g+x" {} +
# strip down to ${WSO2_PROFILE} profile
RUN ${WSO2_SERVER_HOME}/bin/profileSetup.sh -Dprofile=${WSO2_PROFILE}
###
# Setup the runtime image
#
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
ARG WSO2_FULL_NAME
ARG WSO2_SERVER_HOME
ARG APP_BASE_DIR
ARG JAVA_HOME=/opt/jre
ARG JAVA_CACERTS=${JAVA_HOME}/lib/security/cacerts
# destination WSO2 JKS stores
ARG WSO2_CLIENT_TRUSTSTORE_JKS=${WSO2_SERVER_HOME}/repository/resources/security/client-truststore.jks
ARG WSO2_CARBON_JKS=${WSO2_SERVER_HOME}/repository/resources/security/wso2carbon.jks
COPY --from=builder --chown=root:root ${WSO2_SERVER_HOME} ${WSO2_SERVER_HOME}
COPY --chown=root:root local/docker-entrypoint.sh ${WSO2_SERVER_HOME}
COPY --from=jenkins/jenkins:rhel-ubi9-jdk21 --chown=root:root /opt/java/openjdk/ ${JAVA_HOME}
RUN ${JAVA_HOME}/bin/keytool -importkeystore -srckeystore ${JAVA_CACERTS} -destkeystore ${WSO2_CLIENT_TRUSTSTORE_JKS} -srcstorepass changeit -deststorepass wso2carbon -v; exit 0;
# WSO2 needs to change permissions before starting! A script was written only with shell commands, without installing any extra tool.
COPY --chown=root:root local/change_permissions.sh /
RUN chmod +x /change_permissions.sh && \
sh /change_permissions.sh "u=rwx,g=rwx,o=rx" ${WSO2_SERVER_HOME}
### Delete packet manager stuff
RUN rm -fr /var/cache/* /var/lib/dnf /var/lib/rpm /var/lib/rpm-state /etc/yum.repos.d /etc/dnf
WORKDIR ${WSO2_SERVER_HOME}
ENV WORKING_DIRECTORY=${WSO2_SERVER_HOME} \
WSO2_SERVER_HOME=${WSO2_SERVER_HOME} \
JAVA_HOME=${JAVA_HOME} \
WSO2_APIM_VERSION=${WSO2_FULL_NAME}
EXPOSE 5672 8672 8280 8243 9099 9443 9611 9711 9763 9999 11111
In this sample docker file, we have used a “builder” that acts as a temporary image and we have installed all necessary images and download our WSO2 APIM and we can also all other needed library like any database connector or messaging libraries and then unzip them and install( copy them in dropin or lib directory).
RUN ${WSO2_SERVER_HOME}/bin/profileSetup.sh -Dprofile=${WSO2_PROFILE}
Latest command in builder is above line. It is responsible to optimize the current APIM setup for specified profile that is passed to “WSO2_PROFILE” variable. It would remove unnecessary files for each profile. From now on we have a optimized version of APIM setup.
In this example we have called a “local/change_permissions.sh” bash file that is responsible for setting permission for copied folder and files from builder. The sample code is available in Yenlo repository.
Build
Now we are ready to build this file in OpenShift environment. We have defined two docker file. Simple and optimized. For simple one, you have to create a “BuildConfig” in your OpenShift cluster. You can choose Binary as its source type and “wso2-apim-simple” as its name, then by calling below command in your simple dockerfile directory, build image starts to create image based on your dockerfile. After successful finish, it would create an image inside cluster image repository and it is available for use.
oc start-build wso2-apim-simple –-from-dir .
For Optimized one, we have to create 3 different “BuildConfig”. You have to pass all needed variable to it. One of most important variable is “WSO2_PROFILE”, you have set. For each file you have to use one of these profile names:
- gateway-worker
- control-plane
- traffic-manager
Suppose you name them wso2-apim-gw, wso2-apim-cp, wso2-apim-tm and set correct value for each of them in “WSO2_PROFILE” variable, then you by calling below command you can create 3 different image and optimized for their purpose.
oc start-build wso2-apim-gw –-from-dir .
oc start-build wso2-apim-cp –-from-dir .
oc start-build wso2-apim-tm –-from-dir .
Remember that before running “oc” command you have to install “oc cli“ and log in to your cluster in the OpenShift environment.
Conclusion
Deploying WSO2 API Manager (APIM) using RedHat UBI-minimal on OpenShift not only adheres to strict organizational policies but also offers a streamlined, secure, and efficient approach to managing your APIs. By leveraging the lean UBI-minimal image, you can significantly reduce the image size, enhance security, and comply with licensing requirements, making it an excellent choice for modern, containerized environments.
Throughout this blog, we have delved into the intricacies of creating, building, and deploying WSO2 APIM images using UBI-minimal. We’ve explored the essential steps, from understanding the pros and cons of UBI-minimal, to customizing the Dockerfile for WSO2 APIM, and optimizing it for specific profiles. The examples provided demonstrate how to effectively manage dependencies, configure environments, and ensure that your API management solution is both robust and agile.
By following the outlined procedures, you can create optimized WSO2 APIM images tailored to your specific deployment needs, whether it’s for a gateway worker, control plane, or traffic manager. This not only improves performance but also ensures that each component is perfectly suited for its role within the distributed architecture.
As APIs continue to drive innovation and connectivity in modern applications, having a solid, efficient, and secure API management solution is crucial. WSO2 APIM on UBI-minimal within OpenShift offers a compelling path forward, combining the best of open-source flexibility with enterprise-grade robustness. Embrace this approach to unlock new levels of efficiency and security in your API management endeavors.