Declarative containers

Declarative containers could be considered as a technology in between a normal container and a container running on FaaS. Let's look at the following imaginary Dockerfile:

FROM openjdk:8

COPY app.jar /app/app.jar

CMD ["/opt/jdk/bin/java", "-Xmx2G", "-jar", "/app/app.jar"]

What do we see here? At the first time of reading, it would look like a normal Dockerfile. Yes, it is. But it's not a declarative way to define an application container. Why?

We already know that this is a Java application doing some work for us. But it has hardcoded some important and brittle configurations, for example, when openjdk:8 pinned the app to use only that implementation, while -Xmx2G limits the memory usage of the app.

All FaaS platforms these days use containers in the same way. They tie some specific configurations into function containers but actually people need a very neutral and portable way of deploying functions.

So what does a declarative container look like?

It looks something like this:

FROM scratch

COPY app.jar /app/app.jar

CMD ["java", "-jar", "/app/app.jar"]

You might think it is impossible to run this container on any runtime at the moment. The answer is you are correct. But I still argue that the application should be declared in the same way. We should remove all brittle configuration out of the Dockerfile as much as possible. Then we should let a new entity, maybe inside a container engine, manage the environment around the application for us.

For example, it is relatively easy to intercept the container creation process then compute the limitation of the memory allowed by the container (via docker run -m for example) and put that value into the command line of java to cap the memory limit at the application level. The entity responsible for this kind of work inside a container engine would be called the Application Profile Manager, as shown in the following diagram:

Figure 9.4: A container engine with the application profile manager

The crosscutting concept like this is nothing new. We already have a similar concept applied to Docker. Guess what? It's the security concern. Docker already has the AppArmor default profile applied to each running container with the AppArmor subsystem enabled. That's about security concerns. This is at the more application-specific level of concern, so why don't we have a similar concept to help make our life easier?

With this concept, container images would become declarative containers as there is no specific environment or configuration hardcoded for them. And it's the responsibility of the Application Profile Manager to selectively apply an appropriate profile for the container and make it work nicely.

What is the practical benefit of declarative containers? Here's a concrete explanation for the Java app we discussed earlier.

In the world of Java, the application architecture has been designed to decouple between the application and the runtime. With the very strong specification of the JVM, the JVM for running applications is always swappable and replaceable. For example, if we start running an application with an OpenJDK, and we are not happy with its performance, we can safely swap the JVM to be the Zulu JVM or the IBM J9.

With the declarative approach to containers, the Java runtime would be easily swappable on-the-fly without rebuilding the Docker image. It also allows you to apply JVM hot fixes to the running system.

We can download the modified version of Docker with this declarative feature for Java from http://github.com/joconen/engine.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset