How to structure my application in docker?

Hello all, I’m new to docker and have been tasked with testing docker as proof of concept for one of our applications. I have a few questions about how to structure the project.

In general I’m having issues understanding how much I should split-up what is today an application running multiple artifacts(.jar, .war, .ear) on a Wildfly application server, using ActiveMQ as queueing, into different images/containers.

Today the application architecture is approx.:

  • openSUSE
    • Wildfly
      • GUI backend API artifact
      • GUI frontend artifact
      • Business Logic Engine artifact
    • ActiveMQ

Would it be natural to have one docker container containing os/application server and have all artifacts deploy on this docker container?

  • How would you deploy changes? Build a new image? Replace the artifact on the application server inside of the container? If we want to be able to deploy changes to one artifact without shutting down other artifacts how would that affect the architecture?

Our application uses ActiveMQ for queueing.

  • Would it be normal to have ActiveMQ be on its own container? Or can/should it be “bundled” into the image/container with the application server?

Thank you for reading.

General rule of thumb: if components communicate with other component over the network, it makes sense to split them out into their own image.

A container is supposed to be self-contained. Whatever the component needs to run, needs to be in the image.

The ci-pipeline that builds your custom application component should create a new image. Though, it depends on whether you have a mono-repo for all components, or a repo per component. Personally, I try to avoid mono-repos if possible, as it makes the whole pipeline design cumbersome.

Thank you for your reply. I had summer vacation the weeks after I created the thread, so forgot to answer, sorry.

If I understand you correctly we should not try to recreate the server environment we have today, but split it up into multiple containers.

But how do you then handle overhead and other tasks that the application server is supposed to manage?

For this one application, excluding the ActiveMQ, we would need 9 containers. All having the overhead of OpenSUSE and Wildfly. Which would be ~1GB of overhead for each container?

Also all the responsibilities of Wildfly (the application-server) such as delegating the database pools fairly to the different deployments? Same with max api threads etc.?

This one application have two repositories, backend and frontend, with different modules creating in total 9 artifacts. These are today complied in TeamCity and deployed to a Wildfly server on one of our production servers.

Nope. You might want to google for the difference between containers and vm, there are plenty of blog posts that describe the difference. A container does not boot, and does not start system services. It just starts whatever is specified as ENTRYPOINT and/or CMD in the Dockerfile of the image.
Though, if run n-wildfly based containers, you would have n times the overhead of running wildfly.

I don’t have enough to context information to give you good answers on your question. You need to share are details required to understand the whole scenario.

Thank you for your reply.

In Wildfly you can configure the number of max pools for your datasource. Let’s say we have a max pool limit of 40. Then all of my deployment artifacts have to share the pools, and Wildfly will delegate the pools. In some situations maybe artifact A needs 30 and the rest will share the remaining 10. But an hour later artifact A will only use 5 and the rest can share the remaining 35.

If I split my deployments/artifacts into different containers, I would not be able to have Wildfly delegate the pools efficiently between the artifacts depending on need. But would have to preconfigure my containers in such as way that the maximum possible pools used if all artifacts were running 100% would be 40, not to blow the DB pool budget.

I might be missing something very crucial here, because of my very limit knowledge with Docker.

But I don’t wanna waste your time asking questions that might be answered on page 10 on the “How to use docker” documentation.

My first goal will have be to replicate our current production environment in docker, with the purpose of using it locally for easier setup of the project for new developers. (One button configuration). That way we can accumulate experience over time before possibly using it in our test/production environment. So I will start with having one container with OpenSUSE, one Wildfly with 9 deployments.

If the database has a connection limit, I can understand why you want to use a single connection pool to manage all connections, and end up with a single container.

It could be perfectly fine to deploy different artifacts in the same container, as long as they are components of the same application. Though, adding artifacts that are not related to each other in the same container, is not really the container approach.

A container should be self-contained. Thus, its image should include the main application, all its dependencies, an environment neutral default configuration, and an entry point script that uses environment variables to customize the default configuration to be environment specific. It is also valid to mount environment specific configs instead… Mounting volumes with war files on the other side breaks the self-contained constraint - which is fine in development, but should not be done in production.