How to Containerize the Mule


In the last few years, I’ve got a few customers asking me if the Mule Runtime can be containerized. The answer is yes, and in this post I wanted to prove it. So, in this post we will run a small proof of concept. We will create a Docker image of the Mule runtime and deploy a container from that image. This way we will see, first hand, that Mule can be containerized. 

In the image we will build, we will try to replicate all the steps that we followed in an installation of a Standalone runtime on an Ubuntu Server. We’ll use this post as a reference - How to install the Mule Runtime on Ubuntu Server

The goal of this post is not to create an optimal image.

Prepare the Mule Runtime Files

First, we need to prepare the files to build the image. For that, choose a folder in your laptop (or docker host). That will be our docker image folder.
Next, we need to get the Mule Runtime binaries. Go to the Official Mulesoft Site and download the binaries for Linux of the last mule runtime version (at the time of writing this post, that’s mule 4.8.0).
Copy that zip file into our docker image folder.

Create Dockerfile

A Dockerfile is a text file that contains the series of instructions we need to create a Docker image. Each instruction in the Dockerfile defines a step in building the image, such as specifying a base image, copying files, running commands, setting environment variables, or exposing ports. Docker reads the Dockerfile and executes its instructions to generate an image, which can then be used to create and run containers. 

For that, create a file called dockerfile in our docker image folder. For our Mule Runtime image this is the Dockerfile we’ve defined:

FROM ubuntu:24.04

# Create installation folder
RUN mkdir /mule

# Install Java JDK and tools
RUN apt-get update && apt-get install -y openjdk-17-jdk
RUN apt-get install unzip

# Copy Mule Runtime files into the container and extract the files
ADD mule-ee-distribution-standalone-4.8.0.zip /mule
RUN unzip /mule/mule-ee-distribution-standalone-4.8.0.zip -d /mule && \
rm /mule/mule-ee-distribution-standalone-4.8.0.zip

# Set environment variables
ENV MULE_HOME=/mule/mule-enterprise-standalone-4.8.0
ENV PATH=$MULE_HOME/bin:$PATH

# Set work directory
WORKDIR $MULE_HOME

# Define Volumes
VOLUME $MULE_HOME/apps
VOLUME $MULE_HOME/conf
VOLUME $MULE_HOME/domains
VOLUME $MULE_HOME/logs

# Expose HTTP ports for Mule Apps
EXPOSE 8081-8091

# Expose ports for the Mule Cluster
EXPOSE 5701-5703
EXPOSE 54327

# Expose ports for the Mule Agent
EXPOSE 9999
EXPOSE 9997

# Run the Mule
CMD ["mule"]

Let’s break it down:

1. Base Image

FROM ubuntu:24.04

This is the our base image. Here we’re using an Ubuntu image, just because we want to replicate all the steps that we do when we install a Mule Standalone instance as part of this proof of concept. But, in the real world, we would use a much lighter image such as Alpine to reduce as much as we can the size of the image and reduce everything that is not necessary to run the Mule


2. Create Installation folder

RUN mkdir /mule

We create a folder called Mule where we’ll be copying the mule binaries for the installation

3. Install Java JDK and tools

RUN apt-get update && apt-get install -y openjdk-17-jdk
RUN apt-get install unzip

With these instructions we install the Java JDK (required to run Mule). In this tutorial, we’re installing version 17, compatible with the mule 4.8 version we’ll be installing in this image.

The binaries of the mule will be compressed with zip, that’s why we need to install unzip.

4. Copy Mule Runtime files into the container and extract the files

ADD mule-ee-distribution-standalone-4.8.0.zip /mule
RUN unzip /mule/mule-ee-distribution-standalone-4.8.0.zip -d /mule && \
rm /mule/mule-ee-distribution-standalone-4.8.0.zip

In here, we’ll be copying the zip file with the mule runtime we’ve downloaded and unzipping it in our Mule installation folder. After that we removed the zip file, as we don’t need it anymore, so that we save some space in our image.

Make sure the zip file is located in our docker image file, otherwise the image won’t be able to copy the binaries.

5. Set environment variables

ENV MULE_HOME=/mule/mule-enterprise-standalone-4.8.0
ENV PATH=$MULE_HOME/bin:$PATH

We set the MULE_HOME environment variable for the mule runtime and update the PATH env variable, so that we can run Mule commands from any location within the container


6. Set work directory

WORKDIR $MULE_HOME

The WORKDIR keyword sets the current working directory in the container to the MULE_HOME we’ve set up in the previous step. Any command after this instruction we’ll be run from this directory

7. Define Volumes

VOLUME $MULE_HOME/apps
VOLUME $MULE_HOME/conf
VOLUME $MULE_HOME/domains
VOLUME $MULE_HOME/logs

These volumes will retain data even if the container is stopped or removed. Declaring a volume in the image ensures that data written to that location is stored outside the container's writable layer, making it persistent and not tied to the lifecycle of the container. We create specific volumes for the mule runtime folders in which data persistency is required:

  • apps - All the apps deployed to the mule runtime using this image will be stored here
  • conf - Location for all configuration files, cluster files, object stores...
  • domains - Configuration of the domain projects
  • logs - Location for the logs of all of our apps and the runtime
Defining Volumes in the image is not mandatory but it can be very helpful. We could define the same volumes when running the container but this way we make sure these volumes will be always created.

8. Expose Ports

EXPOSE 8081-8091
EXPOSE 5701-5703
EXPOSE 54327
EXPOSE 9999
EXPOSE 9997

In the image we’ve defined the following ports to be exposed:

  • 8081 - 8091: The range could be different. These are the ports we reserve for the Mule Apps
  • 5701-5703, 54327: These are the communication ports between nodes in a Mule cluster, in case we wanted to create a cluster with runtimes in containers.
  • 9999, 9997 : These are the ports use by the Mule Agent to communicate with the runtime plane.

9. Run the Mule

CMD ["mule"]

The last step is to specify the process the container will run, which in our case is the Mule runtime. We can use just 
muleas a command, no need to specify the whole path, because we added it to the PATH env variable

Build the Docker Image

Once the Dockerfile is ready we just need to run the following command to build the image:
docker build -t mule-runtime:4.8 .

Where 
-t flag assigns a name and an optional tag the Docker image. in this case:
  • mule-runtime:The name of the image. This is the identifier used to reference the image.
  • 4.8: The tag assigned to this image. Tags help distinguish different versions of an image. This way we could have an image for each mule runtime version.
The dot (.) specifies the build context, which is the directory containing the Dockerfile and other necessary files (e.g., configuration files, application packages). Docker sends this directory to the Docker daemon during the build process.

Run the container

Run the container using the docker run command:
docker run -d --name mule -p 8081:8081 mule-runtime:4.8

Where:

  • -d - to run the container in the background
  • --name mule Provides a name for our container
  • -p 8081:8081 Maps the port 8081 in the host to the port 8081 in the container. This is the port we’ll use to expose our app. If we needed more ports/apps we will have to map them here. Also, if we wanted to create a cluster we’d need to open the specific ports for that (see above in the exposed ports of the image)
  • mule-runtime:4.8 The full tag of our image

Verify

Once our container with the Mule runtime is app and running, there are a couple of things we can check to see that’s working.

Check the logs

If we check the logs we should find the messages of the start up of the Mule. From your Docker desktop you can access the logs of the container, of from a terminal run:

docker logs [YOUR_MULE_CONTAINER]


Deploy an app

Create a hello-world app in Anypoint Studio and export the jar file. Then, copy that jar file into the $MULE_HOME/apps folder of the container. Make sure the port of your test app is 8081 if you’re following this example. 

Once copied, it will be automatically deployed and you should be able to test it under http://localhost:8081

Push to a Container Registry

If our test was successful, the last step is to make this image available in your container registry, so that you can share it or use from any of your Docker Hosts or Kubernetes environment.
For that, we’ll do it in two steps:
  • Tag the image
docker tag mule-runtime:4.8 [YOUR_REPO]/mule-runtime:4.8
  • Push it to the registry
docker push [YOUR_REPO]/mule-runtime:4.8
where YOUR_REPO is the public name of your registry or username in docker hub

Previous Post Next Post