There is a lot of confusion around which pieces of your application you should break into multiple containers and why. I recently responded to this thread on the Docker user mailing list which led me to writing today's post. In this post I plan to examine an imaginary Java application that historically ran on a single Tomcat server and to explain why I would break it apart into separate containers. In an attempt to make things interesting - I will also aim to
justify this action (i.e. breaking the application into separate containers) with data and (engineering) logic... as opposed to simply stating that "there is a principle" and that one must adhere to it all of the time.
Let's take an example Java application made up of the following two components:
- A front-end application built on the Struts Web Framework
- A back-end REST API server built on Java EE
As mentioned, this application historically ran in a single Tomcat server and the two components were communicating over a REST-based API... so the question becomes:
Should I break this application into multiple containers?
Yes. I believe this application should be decomposed into two different Docker containers... but only after careful consideration.
Instead of breaking applications up into multiple containers "just because" or in an attempt to adhere to some newfangled principle (e.g. "run only one process per container") - I suggest we think through the engineering requirements to make an informed and intelligent decision. Whether or not all applications should be broken into multiple containers - containerizing them should, at the very least, make your life easier by providing you with a simpler deployment strategy.
Let's pause (briefly) on the analysis of our example application and do some design thinking:
- The JVM is multi-threaded, so you are not necessarily running multiple Unix/Linux processes. In fact, I think this is rightfully confusing to engineers coming from the Java world. Historically, Java developers actually liked having multiple applications running in the same JVM; doing so can, in practice, save quite a bit of memory at scale. Furthermore, web application servers like Tomcat were built from the ground up to support running multiple applications in a single JVM. That's actually one of the main differences between running a simple Java program versus a Java EE application (...which could be comprised of multiple threads and multiple different programs).
- In reality, many applications use multiple processes per container. The Apache Web Server prefork and MPM modules both use multiple processes within a container. Modern web applications featuring event driven programming or the reactor pattern (take, for example, Nginx) actually fire off many sub processes. I would argue, the whole idea of FastCGI, AIO, and the reactor pattern is to offload work to other processes (or threads) and let the kernel handle the I/O. The Linux kernel is quite good at scheduling sub processes. Kubernetes/Swarm and individual Docker containers are not as good at this. Processes (and threads) are about kernel resource allocation; containers are about cluster resource allocation.
- The run one process per container "best practice" is widely cited as a "principle" but sounds a lot (more) like philosophy. As an engineer, I want to understand the technical components and make logical decisions. I would argue that this "best practice" is not even universally agreed upon and its over-application stems from a wide-spread lack of understanding with respect to how Unix works.
- Linux Containers have historically come in many forms and many actually recommend running multiple processes per container. What makes Docker containers any different? Linux containers are essentially the clone() system call, SELinux, and Cgroups; whether they are of a LXC or Docker (through libcontainer) type is mostly irrelevant as the Linux kernel itself "does" the process isolation.
- There are valid times when processes communicate over sockets, through files, over the network, etc. - and - each approach has its own pros and cons. A given application's approach to communication will (most certainly) have an impact on whether or not you want to break your application into multiple containers.
- Separation of code, configuration and data will also play into your ability to break your application into multiple containers (or not). If your application has good separation of code, configuration and data, it should be easy to decompose the application. If your application is very old and not well understood - it may make (unwanted) changes to your file system and could be very difficult to decompose. Note that this is OK (!), you don't have to re-write your application to containerize it. You can still get the benefits of the Docker container format by putting your application into a single container. You will then be able to easily move it around (using a registry server) and deploy it (using docker run).
OK, with some Unix / application 101 out of the way, let's get back to analyzing our example Java application:
- The two Java components as described above seem to be doing very different things. One component is a web front-end, the other is an API server. Since these components are doing different things (i.e they are indeed different services), there is little chance that there would be a performance benefit from being in the same JVM (...though, of course, I can't be 100% certain without actually testing performance).
- These two applications communicate using a REST API (...instead of using sockets, shared memory or files, etc.).
- Generally, if an application contains an API layer and a front-end layer, it can be useful to scale these independently. For example, if the API is also consumed by a mobile application it might be useful to scale it up and down with user load, where the web front-end may not need to be scaled. Conversely, if I scale the web front-end, I may also need to scale the API server portion, but I may only need one more API server for every five web front-ends. Long story short, scaling logic can be complicated and being able to scale these independently with something like Kubernetes could be very useful.
Based on these three observations alone - I would recommend breaking these two components into separate containers. I would also recommend using container orchestration such as Kubernetes or OpenShift to wire the services together. I would not base this decision on "principles" or supposed "best practices", I would base it on the application architecture and some form of informed reasoning.
Here's where things get wild... I submit (to you) a new "best practice", drum roll please:
...yes, if your application / service has good separation of code, configuration, and data, installs cleanly (as installer scripts can make this whole process difficult), and features a clean communication paradigm - it does make sense to break the application up / allocate one service per container.
Fundamentally, I suggest that we all begin to think more rationally about how to put applications into containers. Let's also realize that containerization is more than just philosophy, it's about solving technical pain(s). I love containers and I want to use them (all of the time) - but I also want to do so in an intelligent and informed manner. I'm positive that people have opinions and ideas about containerizing applications - I encourage you to share your thoughts in the comments section below.
執筆者紹介
チャンネル別に見る
自動化
テクノロジー、チームおよび環境に関する IT 自動化の最新情報
AI (人工知能)
お客様が AI ワークロードをどこでも自由に実行することを可能にするプラットフォームについてのアップデート
オープン・ハイブリッドクラウド
ハイブリッドクラウドで柔軟に未来を築く方法をご確認ください。
セキュリティ
環境やテクノロジー全体に及ぶリスクを軽減する方法に関する最新情報
エッジコンピューティング
エッジでの運用を単純化するプラットフォームのアップデート
インフラストラクチャ
世界有数のエンタープライズ向け Linux プラットフォームの最新情報
アプリケーション
アプリケーションの最も困難な課題に対する Red Hat ソリューションの詳細
オリジナル番組
エンタープライズ向けテクノロジーのメーカーやリーダーによるストーリー
製品
ツール
試用、購入、販売
コミュニケーション
Red Hat について
エンタープライズ・オープンソース・ソリューションのプロバイダーとして世界をリードする Red Hat は、Linux、クラウド、コンテナ、Kubernetes などのテクノロジーを提供しています。Red Hat は強化されたソリューションを提供し、コアデータセンターからネットワークエッジまで、企業が複数のプラットフォームおよび環境間で容易に運用できるようにしています。
言語を選択してください
Red Hat legal and privacy links
- Red Hat について
- 採用情報
- イベント
- 各国のオフィス
- Red Hat へのお問い合わせ
- Red Hat ブログ
- ダイバーシティ、エクイティ、およびインクルージョン
- Cool Stuff Store
- Red Hat Summit