Some containers launch a single process, your process.
Some containers launch a "linux distribution" sans kernel, really launching the /sbin/init process, such that you now think you have a complete Linux system, as root, with files and libraries laid out in a way that you expect -- regardless of the conventions of the actual Linux system running your container.
A container can be as cheap as launching a process, since that is all a container really does. It launches a process with a lot of parameters and controls that set up the environment, network, isolated process table, your own root user zero, your own root directory, etc. It's just kernel features that isolate your process so that it has a controlled view of what the network looks like, what the filesystem is, etc.
The other reason to package as a container instead of a WAR or JAR is that other DevOps or sys admins can install your container without knowing anything about Java. They don't even have to know that you are using Java. I can get a container and install it and run it so that it does some specific function, and I don't care what technology the developers used. Java, Python, PHP, C, God forbid Perl, it doesn't matter. Maybe the container has a mini-Linux distribution inside it. Maybe not. I don't care, I don't know. The container just plugs in and runs. Think of a Container as the benefits of a WAR / JAR but for a larger world outside of Java.
A container is also a great way to package a legacy application. Or an application using a technology unfamiliar to those deploying it on servers. Your container has all of your dependencies. A specific Java. Specific dependencies, regardless of what the host system has.
You can probably use for defining and spinning up new servers (with JRE, database, servlet container and so on) though but that's a different story.
There is still one however -- Kubernetes. Run many instances of a Docker container in Kubernetes as a cluster.
Oh, but I can set up various Java technology clusters without Kubernetes.
Think of Kubernetes as doing for clusters what an OS does for a single computer.
1960s: Joe: can I use the computer today to run my workload? Bob: yeah, but my workload is running the computer until about 3 PM.
Today: Joe: can I use the (let's say Hadoop) cluster to run my workload? Bob: yeah, but my workload is running the cluster until about 3 PM.
An OS lets Joe and Bob both use the computer at the same time.
Kubernetes lets Joe and Bob both use a generalized cluster at the same time.
Joe has his Docker container (say a Java workload set up as a Hadoop node).
Bob has his Docker container (say some other kind of Java parallel computing workload, or maybe Python or other).
Joe tells Kubernetes to run 50 instances of his workload.
Bob tells Kubernetes to run 30 instances of his workload.
Joe and Bob's workloads can each see each their own nodes on a private network that cannot see the other's nodes on the network.
Maybe the physical hardware cluster only has 45 nodes. Kubernetes might schedule multiple docker containers running on the same physical node.
Kubernetes is something you would expect from Google running a giant data center where many different people want to run multiple-node clusters ad-hoc at any given time. Even multiple instances of the same type of workload, such as Jane wanting her own 50 node Hadoop, while Carol runs a 40 node Hadoop cluster, but they don't interfere with each other.
For what I am working on a deployment takes a couple of seconds including controlled shutdown and startup of the application.
I don't know how fast docker/jib would be but I am imagining this would be a somewhat heavier setup?
> [JRE version] would change very rarely.
It's optimizing for setting up new machines and having everything about how to run an application contained within that application itself rather than relying on sysadmins to `yum install` things or whatever. Plus with docker you always run the same version in prod that you do in dev (and on your local machine) unless you intentionally do something else.
> I don't know how fast docker/jib would be but I am imagining this would be a somewhat heavier setup?
Not really - a layered docker image may have tomcat as a base layer and then the app jars etc layered atop. Deployment is just downloading a new layer which wouldn't really be any overhead atop of just the jars.
When I a deploy WAR-file it, it is fairly small (just app + dependencies), and startup / shutdown is well-defined and happens fast, allowing me to update an application with just a few seconds downtime. But here - how fast would an update be? How much downtime? Does it reinstall the os, the vm, the app, are the shutdown / startup operation well defined or does the process just get killed?
Wouldn't it take quiet a bit of work just to match what you get out of the box in a traditional setup?
> Does it reinstall the os, the vm, the app,
No. First, "reinstall" isn't the right word. The "OS" is baked into the container. There is no vm, Docker is not a vm. It doesn't re-install the app, it's starting it up in a new container. All your deploys are likely doing is pulling a new container image or layer (about the same size as your war) and calling `docker run` which could be more or less the same as `java -jar...`.
> are the shutdown / startup operation well defined or does the process just get killed?
There is a well-defined container lifecycle that iirc sends SIGTERM by default. This is similar to what systemd or similar would do.
If there is a problem with the new code, just point the traffic back to the working container and kill the new container.
Up to a very limited point. JVM backward compatibility is very good so you can do global version upgrades with reasonable confidence, and the JVM is such a common requirement (in the context of being a java shop) that including it in the base system image makes sense.
> plus whatever file-system resources like logging locations etc.
It's very much doable to get these down to zero (e.g. using remote logging), and I find it's worthwhile.
I upgraded a whole java shop to java8 and it was not a fun experience having two JVMs on the same machine and all the different tools thought they knew which one was the correct one but none of them agreed (it wasn't as simple as setting JAVA_HOME).
All of this java tooling/versioning is simple in theory since java is a pretty simple ecosystem (compared to something like C++ or even python to an extent), but there's so many layers of indirection in a modern build & deployment system that it's really painful to debug when some tool somewhere sets its PATH incorrectly or doesn't respect JAVA_HOME or symlinks or....)
If the apps had been docker-ized there wouldn't have needed to be a JVM on the host machine at all, and teams could come in and use java9 or whatever without having to work with SREs/devops to upgrade the machines and worry about whatever other apps may be using those machines or virtual-machine images.
I agree that having two JVMs on the same machine without something like docker can be problematic, but in my experience there's no need to ever do that - the backwards compatibility is good enough that you can just replace the old JVM with the new one.
I mean, if you're worrying about this kind of thing shouldn't you also worry about whether apps are built against older versions of docker? How easy is it to have two different versions of docker on the same machine and make sure that docker upgrades don't impact other apps running on those machines?
Your layer, the top most layer, might have only your JAR. Assembling and deploying your container could be very fast -- but docker takes care of that. You could organize your container so that you have a layer with your Tomcat. Another layer with your JVM. Then you can easily swap in / out layers to define different versions of your container.
Whoever deploys your container on a server doesn't know or care what technology you use. Java, Python, etc. They just plug in the container and it runs. (Docker assembles its layers.)
With a container, they just plug in your application and it runs. They don't know and don't care what technology it was developed with.
You have complete control of your dependencies, which exact Java runtime you use, any other native libraries or tools you use, etc. They are all part of your container and independent of the host system. You can't see the host system, and the host system doesn't care what is in your container.
The container is like a giant simple JAR file for any technology that runs on a Linux system.
Once you know how to install and run a container, you can run apps developed in unfamiliar technologies. You don't have to know about their conventions for paths, or classpaths, or other things you don't care about. That is all packaged up inside the container.
...and that's exactly what Docker + Java does.
Just in a standard format that works with any kind of program, Java or otherwise.