1

What are the principles for app deployment in docker?

I see two concepts

  1. Create image per app version
  2. Create app binaries and somehow deploy them to container(utilize i.e. Tomcats hot deploy)

Maybe there are others, I personally like the first, but there must me tremendous amount of data, if you release very often. How would one choose one over the another?

I'd like to know how others deploys their java application so I can make my personal opinion.

Zveratko
  • 2,663
  • 6
  • 35
  • 64

1 Answers1

0

Update 2019: See "Docker memory limit causes SLUB unable to allocate with large page cache"

I mentioned in "Docker support in Java 8 — finally!" last May (2019), that new evolutions from Java 10, backported in Java 8, means Docker will report more accurately the memory used.

As mbluke adds in the comments:

The resource issues have been addressed in later versions of Java.
As of Java SE 8u131, and in JDK 9, the JVM is Docker-aware with respect to Docker CPU limits transparently.
Starting with Java JDK 8u131+ and JDK 9, there’s an experimental VM option that allows the JVM ergonomics to read the memory values from CGgroups.
To enable it on, you must explicit set the parameters -XX:+UnlockExperimentalVMOptions and -XX:+UseCGroupMemoryLimitForHeap on the JVM Java 10 has these set by default and there is no need for the flags.


January 2018: original answer

As any trade-off, it depends on your situation/release cycle.

But do consider also Java might be ill-fitted for a docker environment in the first place, depending on its nature.
See "Nobody puts Java in a container"

So we have finished developing our JVM based application, and now package it into a docker image and test it locally on our notebook. All works great, so we deploy 10 instances of that container onto our production cluster. All the sudden the application is throttling and not achieving the same performance as we have seen on our test system. And our test system is even this high-performance system with 64 cores…

What has happened?
In order to allow multiple containers to run isolated side-by-side, we have specified it to be limited to one cpu (or the equivalent ratio in CPU shares). Unfortunately, the JVM will see the overall number of cores on that node (64) and use that value to initialize the number of default threads we have seen earlier. As started 10 instances we end up with:

10 * 64 Jit Compiler Threads

10 * 64 Garbage Collection threads

10 * 64 ….

And our application,being limited in the number of cpu cycles it can use, is mostly dealing with switching between different threads and does cannot get any actual work done.

All the sudden the promise of containers, “Package once, run anywhere’ seem violated…


So to be specific, how to cope with the amount of data generated when you do build image per release? If you build your app everytime on top of tomcat image, the disk space needed for store the images will grow quickly, right?

2 techniques:

  • multi-stage build to make sure your application does not include anything but what is need at runtime (and not any compilation files). See my answer here;
  • bind mounts: you could simply copy your wars in a volume mounted by a single Tomcat container.
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I too agree with this comment. The only point I see one to put java app in docker is to ease out the configuration. Otherwise, its easier to remove the docker layer from running application. – Abhay Dandekar Jan 11 '18 at 05:59
  • Interesting read. I'm reading a lot about docker, but never heard of some problems with dockerizing java apps before. And yes it is more for easing the setup and maintenance. – Zveratko Jan 11 '18 at 06:02
  • Maybe we can forget about java. So to be specific, how to cope with the amount of data generated when you do build image per release? If you build your app everytime on top of tomcat image, the disk space needed for store the images will grow quickly, right? – Zveratko Jan 11 '18 at 06:12
  • [This](https://codefresh.io/blog/java_docker_pipeline/) addresses the problem of image sizes – Zveratko Jan 11 '18 at 06:17
  • @Zveratko I have edited my answer, by the way. And one of my recommendation is the same as the one from your other question: https://stackoverflow.com/questions/48201096/share-executable-between-docker-images/48203249#comment83387977_48203249 (volumes, one of the "bind mount" types) – VonC Jan 11 '18 at 16:20
  • Using the bind mounts for JDK would there be any access rights issues? The problem you mentioned must be resolved the same way as for java directly in container, right? – Zveratko Jan 12 '18 at 04:47
  • The resource issues have been addressed in later versions of Java. As of Java SE 8u131, and in JDK 9, the JVM is Docker-aware with respect to Docker CPU limits transparently. Starting with Java. JDK 8u131+ and JDK 9, there’s an experimental VM option that allows the JVM ergonomics to read the memory values from CGgroups. To enable it on, you must explicit set the parameters -XX:+UnlockExperimentalVMOptions and -XX:+UseCGroupMemoryLimitForHeap on the JVM Java 10 has these set by default and there is no need for the flags. – mbluke Sep 11 '19 at 08:23
  • @mbluke Yes, I mentioned it last May: https://stackoverflow.com/a/56153528/6309. And last month: https://stackoverflow.com/a/57345260/6309. I will edit this answer as well. Thank you. – VonC Sep 11 '19 at 08:30