Published on January 7, 2015 by Nicolas Barbé
Edit: In February 2015, Docker Inc released Docker Compose that will replace Fig in the future. This post has been updated accordingly.
We have seen in the last post how to use the magnolia base image to deploy an existing WAR file. Even though this approach looks handy, it is not enough to build-up a production grade environment with Magnolia.
Several aspects have not been discussed - such as using an external service for the database or like the communication between two different Magnolia instances.
In this post, I explain how to setup one Magnolia author instance and its public instance.
The author instance is used by editors to create and edit content. Once an article is ready, it is activated to the public instance, which is the only one accessible on Internet.
How many containers?
A best practice is to use one container per process and to decouple each container as much as possible : A Magnolia instance runs inside its own container, and uses a dedicated database. As a consequence, we need 4 containers (in green) :
How to use my own WAR
If you don't have any Maven project available, create a new one using the Maven archetype from an empty folder:
mvn archetype:generate -DarchetypeCatalog=https://nexus.magnolia-cms.com/content/groups/public/
You can find more details and a great tutorial in the official documentation.
After successfully building the project, Maven creates a target folder inside the webapp module with the WAR file. The next step is to send this WAR file to the docker container.
Create a new Dockerfile inside the root directory of your project with the following content:
COPY my-project-webapp/target/my-project-webapp*.war $CATALINA_BASE/webapps/ROOT.war
The benefit of this approach is to tie the deployment directive and the code in a version control such as GIT and to share this information easily accross the project. All Developers but also operators use the same deployment procedure and infrastructure.
How to distinguish each Magnolia instance
With this approach, the WAR file is deployed in the ROOT context of Tomcat. As a consequence the default magnolia.properties is always picked-up.
In order to keep one single WAR file with multiple configurations, I chose a similar approach than the one described by Greg in his excellent post. However, instead of using a Tomcat context parameter to configure the type of the instance, I inject an environment variable called INSTANCE_TYPE.
You must modify your web.xml to pick-up the right magnolia.properties depending on the value of this environment variable:
In a similar manner, I will define another variable called DB_TYPE to define the type of the database.
Now comes the most interesting part - How to configure and orchestrate my containers?
We have 4 containers, we could start them from the command line directly or we can use Docker Compose.
Docker Compose allows you to define your services and their relationships. The easiest way to understand how it works is to use it!
Create a file called docker-compose.yml in the root directory of your project:
And execute this command:
Docker creates automatically 4 containers:
The public instance is available at this address http://localhost:3001 and the author instance at this address http://localhost:3000. If you are using MacOS, don't forget to replace the localhost by the IP address of the boot2docker virtual machine.
The last step is to configure the public instance as a subscriber.
In an ideal world, at least two public instances are needed for redundancy and a load-balancer must be configured to dispatch the requests automatically. This will be treated in a next post!
The source code of this post is available here.
Nicolas Barbé is a software engineer and technology enthusiast, working for Magnolia as a Senior Consultant. He brings his experience to clients who need expertise in various fields such as integration, deployment approaches, migration, site configuration or prototyping. In this blog, he'll focus on DevOps and tricks for easier developing with Magnolia.
See all posts on Nicolas Barbé