How to Run a Mendix App in a Docker Container in Seconds

on December 23, 2013

Imagine if you could setup a new Mendix hosting environment in seconds, everywhere. A lightweight, secure and isolated environment where you just have to talk to a RESTful API to deploy your MDA (Mendix Deployment Archive) and start your App.

Earlier this year a great piece of software became very popular to help to achieve this goal: Docker. Docker provides a high-level API on top of Linux Containers (LXC), which provides a lightweight virtualization solution that runs processes in isolation.

Mendix on Docker


Run a Mendix App in a Docker container in seconds:


There has been a lot of buzz around Docker since its lauhch in March 2013. Being able to create an isolated environment once, package it up, and run it everywhere is an exciting proposition. Docker provides easy-to-use features like Filesystem isolation, Resource isolation, Network isolation, Copy-on-write, Logging, Change management and more.

For more details about Docker, please read “The whole story”. We’d like to go on with the fun stuff.

Mendix on Docker

Once a month Mendix organizes a so-called FedEx Day (Research Day, ShipIt day, Hackatron). On that day, Mendix developers have the freedom to work on whatever they want. We played with Docker a couple of Research Day’s ago, just to see how it works. But this time we really wanted to create something we’d potentially use in production: a proof of concept of how to run Mendix on Docker.

The plan:

  1. Create a Docker Container containing all software to run Mendix
  2. Create a RESTful API to upload, start and stop a Mendix App within that container

What about the database, you may be wondering? We’ll just use a Docker container that provides us a PostgreSQL service! You can also build your own PostgreSQL container or use an existing PostgreSQL server in your network.

Start off with an image:

This is what we are building: a Docker container containing:

  • All required software to run a Mendix App, like the Java Runtime Environment and the m2ee library
  • A RESTful API (m2ee-api) to upload, start and stop an App (listening on port 5000)
  • A webserver (nginx), to serve static content and proxy App paths to the Mendix runtime (listening on port 7000)
  • When an App is deployed the Mendix runtime will be listening on port 8000 locally

Building the base container

Before we can start to install the software, we need a base image: a minimal install of an operating system like Debian GNU/Linux, Ubuntu, Red Hat, CentOS, Fedora, etc. You could download a base container from the Docker Index. But because this is so basic and we’d like to create a Mendix container we can trust 100% (a 3rd party base image could contain back-doors), we created one ourselves.

A Debian GNU/Linux Wheezy image:

That’s all! Let’s show the image we’ve just created:

Building the Mendix container

On top of the base image we just created, we can start to install all required software to run Mendix. Creating a Docker container can be done using a Dockerfile. It contains all instructions to provision the container and information, like what network ports to expose and what executable to run (by default) when you start using the container.

There is an extensive manual available about how to run Mendix on GNU/Linux. We’ve used this to create our Dockerfile. This Dockerfile also installs files like /home/mendix/.m2ee/m2ee.yaml, /home/mendix/nginx.conf and /etc/apt/sources.list. They must be in your current working directory when running the Docker build command. All files have been published to GitHub.

To create the Mendix container run:

That’s it! We’ve created our own Docker container! Let’s show it:

Our container has been published to the Docker Index: mendix/mendix


When you look at the Dockerfile, it shows you it’ll start the m2ee-api on startup. This API will listen on port 5000 and currently supports a limited set of actions:


Now that we’ve created the container and published it to the Docker Index we can start using it. And not only we can start using it: everyone can!

Pull the container and start it.

In this container the RESTful API started and is now listening on port 5000. We can, for example, ask for its status or show its configuration.

To run an App in this container we first need a database server. Pull a PostgreSQL container from the Docker Index and start it.

Now configure Mendix to use this database server.

Upload, unpack and start an MDA:

Check if the application is running:

Great success! We’ve deployed our Mendix App in a completely new environment in seconds.


Docker is a very powerful tool to deploy lightweight, secure and isolated environments. The addition of a RESTful API makes it very easy to deploy and start Apps.

One of the limitations after finishing this is that the App isn’t reachable from the outside world. The port redirection feature from Docker can be used for that. To run more Mendix containers on one host, there must be some kind of orchestrator on the Docker host that administrates the containers and keeps track of what is running where.

The RESTful API provides a limited set of features in comparison with m2ee-tools. When you start your App using m2ee-tools and your database already contains data, the CLI will ask you kindly what to do. Currently the m2ee-api will just try to upgrade the database scheme if needed and start the App without a notice.

Editor’s note: this was a proof of concept of how to run Mendix on Docker. It’s not yet ready for production.

  • Hendrik

    Hmmm… the initial tl;dr instructions doesn’t work on current Wheezy/Jessie and dockers… perhaps the mendix/mendix image changed and needs some extra parameters you didn’t specify??

    Especially the “docker run -d mendix/mendix” doesn’t “keep running” 🙁

  • Pommi

    Hi Hendrik! You are right. The docker container has been updated to v0.3 in March this year. Please follow the instructions here how to use it.

  • wbassler

    Port 5000 is referenced as the “api port” in this post. I examined the Dockerfile and I dont see port 5000 as being exposed. Only port 8000. Is port 5000 supposed to be port 9000 according to the m2ee yaml (the admin port)? Is the admin port used for the m2ee api? I know this post is a bit old.