Image for post
Image for post
Docker image for ActiveMQ 5.x with POstgreSQL

Build a Docker image for ActiveMQ 5.x with a PostgreSQL persistence

In this post we will create a custom Docker image for ActiveMQ 5.x version alongside with PostgreSQL database for message persistence.

Petros Kovatsis
Apr 12, 2020 · 6 min read

Whether you need a queue technology to support your microservices architecture or to asynchronously complete tasks, then ActiveMQ can do the trick for you.

I have used ActiveMQ in various projects and is my top-listed solution, whenever I need a quick and easy integration. After all, it does what it says, message queuing. Oh, it is also a Java based implementation, so yeah, that’s more my cup of tea! :)

To find out more about ActiveMQ, you may always refer to its website.

One great way have the ActiveMQ up and running, apart from installing it locally, is to run it via Docker. Docker is, in a 10.000 feet view, a container engine that allows your applications to run in isolation, wrapped in an environment of your choice. Visit the website for more info.

Another great enhancement, is to have a persistence layer, so that all your messages can be saved on the disk. The advantage of such an implementation, is that if for any reason your ActiveMQ stops, your messages will be saved in the database and as soon as your ActiveMQ is up, they will be scheduled for consumption again. For the purposes of this example, we will be using a locally installed PostgreSQL server.

So, enough with the theory! I assume you are already familiar with all those concepts. Lets create our custom Docker image!

A github link for the full example, lies at the end of the post.

Build the Docker Image

In order to build our Docker image, we need to create the Dockerfile as appropriate. For each step on the file, I give a brief explanation as shown bellow.

Every resource mandatory to run this example, may be found on the gitfub link I provide at the very end of this post.

FROM openjdk:8-jre-alpine (1)

ENV ACTIVEMQ_VERSION 5.15.11 (1)
ENV ACTIVEMQ_WORKDIR /app (1)

RUN mkdir -p $ACTIVEMQ_WORKDIR (2)

COPY activemq/apache-activemq-5.15.11-bin.tar.gz . (3)

RUN tar -xzf apache-activemq-5.15.11-bin.tar.gz -C $ACTIVEMQ_WORKDIR (3)

RUN ln -s $ACTIVEMQ_WORKDIR/apache-activemq-$ACTIVEMQ_VERSION \$ACTIVEMQ_WORKDIR/activemq (4)

COPY conf/activemq.xml $ACTIVEMQ_WORKDIR/activemq/conf (5)

COPY conf/db.properties $ACTIVEMQ_WORKDIR/activemq/conf/db.properties (5)

COPY lib $ACTIVEMQ_WORKDIR/activemq/lib (6)

WORKDIR $ACTIVEMQ_WORKDIR/activemq (7)
EXPOSE 8161 (7)
EXPOSE 61616 (7)
CMD ["/bin/sh", "-c", "bin/activemq console"] (7)

(1) Environment set up

We will use the alpine jre of the openjdk 8 in our environment in order to successfully run the ActiveMQ. We also set a couple of environmental variables holding the values, regarding the working directory and the ActiveMQ version in use.

(2) Create the working directory

The working directory, is where all of our work happens. So, we need to create it first, and for that we will use the variable of the step (1).

(3) Copy the ActiveMQ

Next, we go and copy the ActiveMQ zipped file from our local disk to the Docker image. In our example we are using the 5.15.11 version which can be downloaded from here and must be saved in the activemq directory.

Since I love working on Linux, I can complete the above steps from a command line.

>> mkdir -p activemq>> wget http://archive.apache.org/dist/activemq/5.15.11/apache-activemq-5.15.11-bin.tar.gz -O activemq/apache-activemq-5.15.11-bin.tar.gz

For us to complete this step, we will need to extract the copied file inside the Docker image. Since we are using a Linux distribution wrapped from the image, the appropriate command as shown in the Dockerfile, can do the job for us.

(4) Create a soft link

Now lets create a soft link to the extracted ActiveMQ directory for our convenience. This step may not sound mandatory, and it is not, but is a handy direction for the the upcoming steps.

(5) Copy the configuration files

Now let us move on, to the most critical and essential part of this post. It is time to dictate ActiveMQ, how it should be working and how to connect with the database.

First thing first, the activemq.xml file, is the main configuration file which can be found under the conf directory. Our intention is to override it with one of our own, so that we can achieve the desired behavior. We now may create the conf directory in our local disk and include in it, all the files that should replace the default ones. So, we go ahead and create our own activemq.xml file under that directory. For our convenience, we may copy the default one from our download version and apply the changes.

Create the db.properties file in the local conf directory and add the bellow lines dictating how we should connect with the database. You may introduce changes according to your needs as appropriate. Keep in mind, that our PostgreSQL instance is running in our local machine, hence, we need to include the appropriate host. You may find your own, if for example, you are running under Linux, by executing ip a from a command line, and identify for Docker’s adapter settings. It should probably start with a docker0.

amq.db.host=172.17.0.1
amq.db.dbname=activemq_db
amq.db.port=5432
amq.db.url=jdbc:postgresql://${amq.db.host}:${amq.db.port}/${amq.db.dbname}
amq.db.username=postgres
amq.db.password=postgres
amq.db.init_connections=5
amq.db.max_connections=10

Important! You need to create the activemq_db database yourself. If you prefer another name, change it accordingly on the above configuration as well.

Next, in our local activemq.xml file, we must include the data source bean configuration as shown bellow.

<bean id="postgres-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="${amq.db.url}"/>
<property name="username" value="${amq.db.username}"/>
<property name="password" value="${amq.db.password}"/>
<property name="initialSize" value="${amq.db.init_connections}"/>
<property name="maxTotal" value="${amq.db.max_connections}"/>
<property name="testOnBorrow" value="true"/>
<property name="validationQuery" value="select 1"/>
<property name="poolPreparedStatements" value="true"/>
</bean>

Finally, we must tell ActiveMQ to use our data source instead of its predefined in memory storage.

<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#postgres-ds" lockKeepAlivePeriod="5000" createTablesOnStartup="true">
...
</jdbcPersistenceAdapter>
</persistenceAdapter>

What’s critical here, is the assignment of the posgres-ds been to the persistence adapter. The createTablesOnStartup attribute describes whether we need our tables to be initially created or not. If you run your Docker container for the very first time, then this must be set to true. Otherwise you should switch it to false or else you will keep getting errors in your logs, regarding table creation.

(6) Copy the jar files

In order for the ActiveMQ instance to connect with the database, additional jar files must be included in the image. The ActiveMQ distribution, does not ship with all those needed jar files so we may create a lib directory and put in it all those files. Finally we go and copy that local lib folder to the appropriate path in our image.

(7) Run the ActiveMQ instance

Finally, it’s time to instruct the image to run the ActiveMQ instance. Firstly, we switch our working directory to activemq, we expose the ports for our container and then we execute the appropriate script.

Regarding the ports, the 8161 port is the default port of the web UI to monitor the instance, so we may access it by visiting the http://localhost:8161 from our browser. Use the default admin:admin credentials to access the protected pages. Additionally, we expose the 61616 which is the tcp port for other running services to produce and consume messages.

Run the container

We are approaching to the end of this post, so, is there any better way to test our example other than run it ourselves? :)

As you may already are aware of, we need to trigger the Docker and build our image. As soon as we run our docker image, then a container is created appropriately. Since the container is our running instance of the Docker image, we are able to stop it, start it, deleted it or create another one.

Now, lets first create and tag our Docker image.

>> docker build -t pk/activemq .

By running this command for the very first time, the dependent images will be downloaded. It may take some time to build for the first time, but this waiting time won’t bother you again in subsequent builds. You may execute the docker images from your command line to check whether your newly created Docker image is in place.

Then, we go ahead and run the Docker image. The 8161 port is exposed as we can see bellow.

docker run --rm -d -p 8161:8161 pk/activemq

That’s it folks! You may now access your ActiveMQ instance from your browser.

Image for post
Image for post
Access from browser at http://localhost:8161

I hope this post was helpful for you. You may find all the files available to run this example on github.

Cheers!

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Petros Kovatsis

Written by

Hey there! I am a freelance software engineer, a musician and a photography enthusiast. More about me at petroskovatsis.com.

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Petros Kovatsis

Written by

Hey there! I am a freelance software engineer, a musician and a photography enthusiast. More about me at petroskovatsis.com.

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store