Photo by CHUTTERSNAP on Unsplash

Containerizing Mule Applications using Docker

0Shares

In this article I am going to touch Docker for containerization of Mule applications.

Intended audience: Any one who wants to understand how to containerize Mule applications and no prior knowledge is required to go through. But basic MuleSoft product knowledge is required to follow along.

Before going into containerization, I will briefly touch base with the definition and terms to follow the article.

Containers – Containers provides a mechanism to package an application with all its dependencies and provides isolation for the application environment. Application running in one container will not be affected by other applications. It can be executed on any machine, providing us the portability to transition from Development to Deployment seamlessly.

Docker – Docker is a technology that acts both as packaging format and a container runtime. Packaging is defined in a Docker file and container is created from the image created using the Docker file.

Docker file – A Docker file defines a set of instructions to build an image. The command used is:

docker build

A container is an instance of an image. The image can be deployed or transported to any platform since it is a self-contained and run as container

Docker container is created as below:

docker run

You can store the image in your local machine or a private registry like Azure Container Registry (ACR) or public storages like Docker Hub.

Note: This article deals with only the demonstration of creating an image and creating a container. In future articles, I will discuss more about the container registries. Also, note that since the runtime used is trial version, it is valid only for 30 days. For basic learning it is ok to use trial version. But, to work on your projects, get licensed runtime by contacting MuleSoft.

Pre-requisites:

  • Download the free Mule runtime from MuleSoft’s website.
  • Also, download the Anypoint Studio to develop applications.
  • Install docker from the Docker’s website.

Step 1: Create a separate folder (For example, Docker4.3 in your local machine)

Step 2: Create a Dockerfile with no file extensions in the same folder. Use Visual Studio Code IDE which can detect a Dockerfile.

Step 3: Copy the Mule runtime zip file in the folder created in step 1.

Step 4: Open the Dockerfile and copy the following lines ( I have added comments for each instruction for easy understanding):

FROM java:openjdk-8-jdk

RUN rm -rf Mule
RUN mkdir Mule

#Add  Mule runtime to the Docker container
RUN echo "Adding Mule 4.3.0 to Docker container"
ADD  mule-ee-distribution-standalone-4.3.0.zip /Mule

#Add Work Directory
RUN echo "Adding Work Directory"
WORKDIR /Mule

#Extract and install the Mule runtime in the container
RUN echo "Extracting the zip file and installing the Mule runtime"
RUN         unzip mule-ee-distribution-standalone-4.3.0.zip && \
    rm mule-ee-distribution-standalone-4.3.0.zip

# Define volume mount points
VOLUME      ["/Mule/mule-enterprise-standalone-4.3.0/logs", "/Mule/mule-enterprise-standalone-4.3.0/apps", "/Mule/mule-enterprise-standalone-4.3.0/domains"]

#Copy and deploy mule application in the Mule 4.3.0 runtime
RUN echo "Deploying mule application in runtime"
COPY  simplehttp-1.0.0-SNAPSHOT-mule-application.jar mule-enterprise-standalone-4.3.0/apps/
RUN ls -ltr mule-enterprise-standalone-4.3.0/apps/

# Expose the port 8081 as needed
EXPOSE      8081

# Start Mule runtime
RUN echo "Starting Mule runtime 4.3.0"
CMD         ["mule-enterprise-standalone-4.3.0/bin/mule"]

As specified int he Docker file, we need to create a sample Mule application and in my case it is “simplehttp-1.0.0-SNAPSHOT-mule-application.jar”.

Step 5: Develop a simple HTTP application that is exposed on port 8081 as below:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns:http="http://www.mulesoft.org/schema/mule/http"
	xmlns="http://www.mulesoft.org/schema/mule/core"
	xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
	<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="f7f6140b-9749-469e-a9e8-99a850a52e60" >
		<http:listener-connection host="0.0.0.0" port="8081" />
	</http:listener-config>
	<flow name="simplehttpFlow" doc:id="1b65f4b8-bb63-4d6f-ae3a-964287b317a4" >
		<http:listener doc:name="Listener" doc:id="4a626aaf-4e5d-44c5-bca9-a66cfb2dbc3a" config-ref="HTTP_Listener_config" path="/verify"/>
		<logger level="INFO" doc:name="Logger" doc:id="4803e315-b3e1-4c6e-844f-9fbac6441769" message="Request recieved and sending response"/>
		<ee:transform doc:name="Transform Message" doc:id="441e4a7e-77e5-4bbb-a901-a0f7ef28624a" >
			<ee:message >
				<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
{
	'result':'success'
}]]></ee:set-payload>
			</ee:message>
		</ee:transform>
	</flow>
</mule>

This application when executed will return a JSON message.

Figure 1 – JSON Response

Step 6: Build the jar by running packaging the application.

mvn clean package

Step 7: Copy the jar from the target folder of the application into the folder we created in the step 1.

Step 8: Now build the image by running the following command from the folder created in the step 1.

$ docker build -t ivaturia/simplehttp:latest

You should see the logs similar to the following:

[+] Building 10.3s (18/18) FINISHED                                                                                             
 => [internal] load build definition from Dockerfile                                                                       0.0s
 => => transferring dockerfile: 1.16kB                                                                                     0.0s
 => [internal] load .dockerignore                                                                                          0.0s
 => => transferring context: 2B                                                                                            0.0s
 => [internal] load metadata for docker.io/library/java:openjdk-8-jdk                                                      0.6s
 => [internal] load build context                                                                                          0.1s
 => => transferring context: 1.77MB                                                                                        0.1s
 => [ 1/13] FROM docker.io/library/java:openjdk-8-jdk@sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c  0.0s
 => CACHED [ 2/13] RUN rm -rf Mule                                                                                         0.0s
 => CACHED [ 3/13] RUN mkdir Mule                                                                                          0.0s
 => [ 4/13] RUN echo "Adding Mule 4.3.0 to Docker container"                                                               0.5s
 => [ 5/13] ADD  mule-ee-distribution-standalone-4.3.0.zip /Mule                                                           1.2s
 => [ 6/13] RUN echo "Adding Work Directory"                                                                               0.4s
 => [ 7/13] WORKDIR /Mule                                                                                                  0.0s
 => [ 8/13] RUN echo "Extracting the zip file and installing the Mule runtime"                                             0.4s
 => [ 9/13] RUN         unzip mule-ee-distribution-standalone-4.3.0.zip &&     rm mule-ee-distribution-standalone-4.3.0.z  3.7s
 => [10/13] RUN echo "Deploying mule application in runtime"                                                               0.4s
 => [11/13] COPY  simplehttp-1.0.0-SNAPSHOT-mule-application.jar mule-enterprise-standalone-4.3.0/apps/                    0.0s
 => [12/13] RUN ls -ltr mule-enterprise-standalone-4.3.0/apps/                                                             0.4s
 => [13/13] RUN echo "Starting Mule runtime 4.3.0"                                                                         0.5s
 => exporting to image                                                                                                     2.0s
 => => exporting layers                                                                                                    1.9s
 => => writing image sha256:7dd9023c087a2cdac43dc226574efeb0ccd80ce79e3d88ea615dba178c6a07a3                               0.0s
 => => naming to docker.io/ivaturia/simplehttp:latest   

Step 9: Now run the application in the docker container by running the image as below:

docker run -it --rm -p 9091:8081 ivaturia/simplehttp:latest

Here I am mapping the port 8081 to 9091 so that I can make sure that I am hitting right URL after container is created.

docker run – runs the image and create the container, -it tells it to run in interactive shell in the container (pseudo TTY), -p tells to publish the port on the container 8081 to the port 9091 in the local machine, finally we have to specify the image created in the step 8.

Now you should see the logs as below that you normally see when the Mule application runs in the Anypoint Studio in the Console window.

Running in console (foreground) mode by default, use Ctrl-C to exit...
MULE_HOME is set to /Mule/mule-enterprise-standalone-4.3.0
MULE_BASE is set to /Mule/mule-enterprise-standalone-4.3.0
Running Mule Enterprise Edition...
--> Wrapper Started as Console
Java Service Wrapper Standard Edition 64-bit 3.5.37
  Copyright (C) 1999-2018 Tanuki Software, Ltd. All Rights Reserved.
    http://wrapper.tanukisoftware.com
  Licensed to MuleSoft Inc. for Mule Runtime Enterprise Edition

Launching a JVM...
Starting the Mule Container...
WrapperManager: Initializing...

Valid license key --> Evaluation = true, Expiration Date = Mon Apr 26 00:00:00 UTC 2021, Contact Name = MuleSoft Support, Contact Email Address = support@mulesoft.com, Contact Telephone = support@mulesoft.com, Contact Company = MuleSoft, Contact Country = US, Entitlements = 


**********************************************************************
*                                                                    *
*                         (((((((((((((((((((                        *
*                     (((((                 ((((#                    *
*                  &(((                        *(((                  *
*                &(((                             (((                *
*               (((     (((%               (((#     (((              *
*              ((     (((((((             (((((((    (((             *
*             ((     (((((((((           (((((((((     ((            *
*            ((    #(((((((((((        #(((((((((((    (((           *
*           #((    ((((((((((((((     ((((((((((((((    ((           *
*           ((    ((((((  /(((((((   (((((((  /((((((    ((          *
*           ((    ((((((    (((((((&(((((((    ((((((    ((          *
*           ((    (((((      ((((((((((((*     ((((((    ((          *
*           ((    ((((((      *(((((((((       ((((((    ((          *
*           ((    ((((((        (((((((        ((((((   (((          *
*            ((    ((((((                     ((((((    ((           *
*            ((#    ((((((#                 (((((((    ((            *
*             ((#    ((((((((             ((((((((    (((            *
*              (((    (((((((              (((((     ((.             *
*                ((      (((               (((     #((               *
*                 /((                            (((                 *
*                    (((                      &(((                   *
*                      *((((&             &((((                      *
*                           ((((((((((((((/                          *
*                                                                    *
*    ___  ___      _        ______            _   _                  *
*    |  \/  |     | |       | ___ \          | | (_)                 *
*    | .  . |_   _| | ___   | |_/ /   _ _ __ | |_ _ _ __ ___   ___   *
*    | |\/| | | | | |/ _ \  |    / | | | '_ \| __| | '_ ` _ \ / _ \  *
*    | |  | | |_| | |  __/  | |\ \ |_| | | | | |_| | | | | | |  __/  *
*    \_|  |_/\__,_|_|\___|  \_| \_\__,_|_| |_|\__|_|_| |_| |_|\___|  *
*                                                                    *
*                                                                    *
* Mule Runtime and Integration Platform                              *
* Version: 4.3.0 Build: 5bb13483                                     *
* MuleSoft, Inc.                                                     *
* For more information go to                                         *
* https://www.mulesoft.com/platform/soa/mule-esb-enterprise          *
*                                                                    *
* Server started: 3/27/21 9:27 PM                                    *
* JDK: 1.8.0_111 (mixed mode)                                        *
* JDK properties:                                                    *
*  - java.vendor = Oracle Corporation                                *
*  - java.vm.name = OpenJDK 64-Bit Server VM                         *
*  - java.home = /usr/lib/jvm/java-8-openjdk-amd64/jre               *
* OS: Linux (4.19.121-linuxkit, amd64)                               *
* Host: 0f09507d3c62 (172.17.0.2)                                    *
* Mule services:                                                     *
*  - mule-service-http-ee-1.6.0                                      *
*  - mule-service-weave-ee-2.3.0                                     *
*  - mule-service-scheduler-1.3.0                                    *
*  - mule-service-soap-1.3.0                                         *
*  - api-gateway-events-collector-service-1.1.0                      *
*  - mule-service-oauth-ee-1.0.0                                     *
*  - api-gateway-contract-service-1.1.0                              *
* Applied artifact patches:                                          *
*  - APIKIT-2576-1.3.7-1.3.8-1.0.jar                                 *
*  - APIKIT-2612-1.0.0-1.0.2-1.1.0-1.0.jar                           *
*  - APIKIT-2612-1.1.1-1.0.jar                                       *
*  - APIKIT-2612-1.1.11-1.0.jar                                      *
*  - APIKIT-2612-1.1.12-1.2.0-1.2.2-1.0.jar                          *
*  - APIKIT-2612-1.1.13-1.1.14-1.2.3-1.2.4-1.0.jar                   *
*  - APIKIT-2612-1.1.15-1.1.16-1.0.jar                               *
*  - APIKIT-2612-1.1.2-1.0.jar                                       *
*  - APIKIT-2612-1.1.3-1.0.jar                                       *
*  - APIKIT-2612-1.1.4-1.0.jar                                       *
*  - APIKIT-2612-1.1.5-1.1.6-1.0.jar                                 *
*  - APIKIT-2612-1.1.7-1.0.jar                                       *
*  - APIKIT-2612-1.1.8-1.1.10-1.0.jar                                *
*  - APIKIT-2612-1.2.5-1.3.1-1.3.4-1.0.jar                           *
*  - APIKIT-2612-1.3.0-1.0.jar                                       *
*  - APIKIT-2612-1.3.5-1.3.9-1.0.jar                                 *
*  - APIKIT-2613-1.2.0-1.2.1-1.0.jar                                 *
*  - APIKIT-2613-1.2.2-1.0.jar                                       *
*  - APIKIT-2613-1.2.3-1.2.4-1.3.0-1.0.jar                           *
*  - APIKIT-2613-1.2.5-1.3.1-1.3.4-1.0.jar                           *
*  - APIKIT-2613-1.3.5-1.3.6-1.0.jar                                 *
*  - APIKIT-2613-1.3.7-1.3.8-1.0.jar                                 *
*  - APIKIT-2613-1.3.9-1.0.jar                                       *
*  - SE-12551-1.0.0-1.0.1-1.0.jar                                    *
*  - SE-12551-1.1.0-1.1.15-2.0.jar                                   *
*  - SE-12551-1.2.0-1.3.0-1.0.jar                                    *
*  - SE-12551-1.3.1-1.3.4-1.0.jar                                    *
*  - SE-12562-1.0.0-1.5.5-1.0.jar                                    *
* Mule system properties:                                            *
*  - mule.metadata.cache.expirationInterval.millis = 5000            *
*  - mule.base = /Mule/mule-enterprise-standalone-4.3.0              *
*  - mule.home = /Mule/mule-enterprise-standalone-4.3.0              *
*  - mule.metadata.cache.entryTtl.minutes = 10                       *
**********************************************************************

**********************************************************************
* Cluster configuration                                              *
*                                                                    *
* Cluster mode disabled                                              *
**********************************************************************

**********************************************************************
* Started domain 'default'                                           *
**********************************************************************

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ New app 'simplehttp-1.0.0-SNAPSHOT-mule-application'                         +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Initializing app 'simplehttp-1.0.0-SNAPSHOT-mule-application'                +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

**********************************************************************
* Started DefaultSchedulerService                                    *
*                                                                    *
* Resolved configuration values:                                     *
*                                                                    *
* Pooling strategy:       UBER                                       *
* gracefulShutdownTimeout:       15000 ms                            *
* uber.threadPool.maxSize:         148                               *
* uber.threadPool.threadKeepAlive: 30000 ms                          *
*                                                                    *
* These can be modified by editing 'conf/scheduler-pools.conf'       *
**********************************************************************

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Starting app 'simplehttp-1.0.0-SNAPSHOT-mule-application'                    +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

**********************************************************************
* Started app 'simplehttp-1.0.0-SNAPSHOT-mule-application'           *
* Application plugins:                                               *
*  - Sockets : 1.2.1                                                 *
*  - HTTP : 1.5.24                                                   *
**********************************************************************

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Mule is up and kicking (every 5000ms)                                        +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

**********************************************************************
*              - - + DOMAIN + - -               * - - + STATUS + - - *
**********************************************************************
* default                                       * DEPLOYED           *
**********************************************************************

*******************************************************************************************************
*            - - + APPLICATION + - -            *       - - + DOMAIN + - -       * - - + STATUS + - - *
*******************************************************************************************************
* simplehttp-1.0.0-SNAPSHOT-mule-application    * default                        * DEPLOYED           *
*******************************************************************************************************

Now open Postman or any of your favorite tool and hit endpoint http://localhost:9091/verify and you should see the result as you got when you ran the program but this time on different port i.e. 9091 instead of 8081.

Figure 2 – Response

Now open new Bash window and type the command “docker images” and it will list our image with the IMAGE, ID and other details:

$ docker images
REPOSITORY                           TAG                                                     IMAGE ID       CREATED          SIZE
ivaturia/simplehttp                  latest                                                  7dd9023c087a   18 minutes ago   1.33GB

To view the container, run the command “docker container ls” and it will list our container with the details:

$ docker container ls
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS          PORTS                    NAMES
0f09507d3c62   ivaturia/simplehttp:latest   "mule-enterprise-sta…"   10 minutes ago   Up 10 minutes   0.0.0.0:9091->8081/tcp   clever_northcutt
Akkirajus-MacBook-Pro:~ Master$ 

If you want to delete image, first you need to remove the container and then you can remove the image. You cannot remove image while container is running.

Press ^c in the bash shell window where the container was running in the step 9 and you should see the following:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Disposing application 'simplehttp-1.0.0-SNAPSHOT-mule-application'           +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Disposing domain 'default'                                                   +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<-- Wrapper Stopped

Now if you run “docker container ls” it will not list the container as you have shutdown the container.

Commands nice to know:

To remove container; -f force deletion; ID is the id of the container,

docker rm -f container <ID>

To remove image,

docker rmi <ID>

Now this image is stored in my local computer and in order to make it available, we might need to publish to a public repository like docker hub. You need to register for the free account.

Next step, I am going to push the image to docker hub. Before that I need to make a small change to the image name i.e. ivaturia/simplehttp to akkiraju/simplehttp as my docker hub account name is “akkiraju” and if I try to push the old image, the push request will be denied with the following error:

denied: requested access to the resource is denied

In order to change the name of the image, we can clone the existing image with tag as <accountid>/<imagename>

$ docker tag ivaturia/simplehttp:latest akkiraju/simplehttp

Now run the following command to see if the new image is listed:

$ docker images
REPOSITORY                           TAG                                                     IMAGE ID       CREATED         SIZE
akkiraju/simplehttp                  latest  

Now let’s push the image to the Docker hub with the following command:

$ docker login
$ docker push ivaturia/simplehttp

Once the command is successful, login into the docker hub and check if the repository lists the new image. In my case, I can check the image as shown in the following figure:

Figure 3 – Docker repository

Now the image is available in the repository and so we can remove the local image by using the command docker rmi <image>

If you ever want to download the image you can do so using the command docker pull <image>

Hope this article was useful to just to have a basic understanding of creating an image and container and access the endpoint and publish to docker hub from where others can pull the image and use it.

0Shares