Jack's not wrong. But better to look at it as throwing (increasingly cheaper) compute at the it-runs-on-my-machine problem.
Jack's not wrong. But better to look at it as throwing (increasingly cheaper) compute at the it-runs-on-my-machine problem.
But how is a docker image different from, for example, a statically compiled single-binary Go executable? Because when I work with Go, I tend to think that if what I'm working on requires something defined from outside the binary, I'm doing it wrong.
So is Docker a solution to problems that are inevitable, or is it just a solution to problems caused by other solutions?
These days I tend to think that something like Firecracker is more likely to be a solution to deployment problems than Docker is, but I haven't tried it yet...
Maven or Gradle deals with assembling all the necessary jars into a single directory (or uberjar if you want, I don't like it).
JVM is another directory.
Running application is a shell script of 2-3 lines.
So my Java application is: directory with JVM, directory with jars and start.sh.
It works almost everywhere. It's simpler than docker. I can replace JVM with windows version and start.sh with start.bat and it'll run on Windows. Natively. Can't do that with Docker.
To build my application one would need to have maven (one directory), JVM (another directory) and project sources. Set up two env vars (JAVA_HOME, PATH) and run mvn verify. That's about it. Windows, Linux, macOS, doesn't matter.
Single binary is simpler than a directory with some files. But not much simpler.
I use docker, because that's the way things are done nowadays. I think that for personal project which does not need Kubernetes, I wouldn't use it.
Recently I've done a few migration projects and the biggest pain-point (not really a pain but not k8 friendly) is the containerization of JEE servers/services. As these solved most of what containers provide (deployment wise) albeit only for java. 'DevOps' generally killed this (and the related tech debt) but it's hard to validate the utility of any of this as the 'generalized' solution feels like it's compromised down to a point of convenience.
In saying that I do enjoy having a deployment platform that is always going to be Linux(like).
I don't think I would use it either for a personal project; but I would perhaps investigate how hard it would be to add some level of "kublet" (cri) like jvm integration
Lol, no you don't. You need a fat jar and you need to install the JVM on your servers (and, sure, maybe upgrade it once every three years). In the early days people actually used Java to do the same thing that docker does, by having an "application server" that you would deploy individual java apps into, before realising what a bad idea that was.
> So is Docker a solution to problems that are inevitable, or is it just a solution to problems caused by other solutions?
It's a solution to the problem that Python dependency management sucks. Unfortunately the last 6 or 7 iterations of "no, Python dependency management is good now, we've fixed it this time, honest" suggest that that's inevitable.
I didn't mean to imply that I think Docker exists solely for Java; I didn't realise that Python has the same problems, but it's unsurprising, and there are plenty of other languages/platforms that probably have the same problem. My point was that I have started to think that Docker is a solution to a problem that probably shouldn't exist.
> Lol, no you don't. You need a fat jar and you need to install the JVM on your servers (and, sure, maybe upgrade it once every three years). In the early days people actually used Java to do the same thing that docker does, by having an "application server" that you would deploy individual java apps into, before realising what a bad idea that was.
I'm surprised that you advocate for deploying JVMs to individual production servers; given that Docker exists, per-server JVM installs are quite possibly the worst possible way to manage Java deployment in a production environment. Give me Docker over this any day. Docker is great for Java apps.
As someone else pointed out, one of the benefits of Docker is that you get rid of the "it-runs-on-my-machine" problem: if you want your application to run reliably throughout dev, test and prod, then you must include the JVM in the distribution, because you can't otherwise guarantee that the JVM you're running on is the one you developed and/or tested on.
Don't even get me started on JavaEE: an operating system built by consultants, for consultants.
Using Docker doesn't solve any problems though - instead of installing the right version of the JVM on all your servers, now you have to install the right version of Docker on all your servers.
(In practice if I had more than a couple of servers I'd use Puppet or something to get the right version of the JVM on all of them, sure. But you have the exact same problem when using Docker too).
> As someone else pointed out, one of the benefits of Docker is that you get rid of the "it-runs-on-my-machine" problem: if you want your application to run reliably throughout dev, test and prod, then you must include the JVM in the distribution, because you can't otherwise guarantee that the JVM you're running on is the one you developed and/or tested on.
In theory, sure. In practice, the JVM is tested and backwards compatible enough that those problems don't happen often enough to matter. You can still have "it works on this machine but not that machine" problems with Docker too - different versions of Docker have different bugs that may affect your application.
> Don't even get me started on JavaEE: an operating system built by consultants, for consultants.
I already said it was doing the same thing Docker does :).
In my experience, JVM upgrades can and did cause us all sorts of problems, both subtle and not-so-subtle, depending on how big the upgrade was. Docker resolved a lot of that pain for us by making it possible to upgrade piecemeal, on a per-service basis, when we were ready.
> You can still have "it works on this machine but not that machine" problems with Docker too - different versions of Docker have different bugs that may affect your application.
I haven't experienced this, but in any case, the joy of Docker in a JVM environment with many applications is that you can pin the JVM for each individual application; you aren't forced to use whatever JVM is installed on the machine. This gave developers more freedom, because they could deploy whatever JVM environment they needed.
You can get away with more ad-hoc solutions if you're just one person, but once you have a team of people and a long list of JVM services, you need to be able to delegate control of as much of the operating environment to the developers.
As I said originally, this problem doesn't exist with Go because it emits static binaries that don't generally need additional support files, which is why I'd love to see more discussion on dynamic deployment of binaries instead of docker containers.
If you ever find yourself needing to do this, something's gone very wrong. (Maybe you're using a dodgy framework that mucks around with JVM internals?) You can download jars from 25 years ago and run them on today's JVM no problem, to the point I have a lot more faith in JVM backward compatibility than in Docker backward compatibility.
> As I said originally, this problem doesn't exist with Go because it emits static binaries that don't generally need additional support files, which is why I'd love to see more discussion on dynamic deployment of binaries instead of docker containers.
I actually think the way forward in the long term is unikernels. Given that people are mostly going for a one-application-per-VM/container model, most of what a multiuser OS is designed for is unnecessary. For the cases where you do need isolation, containers aren't really good enough, VM-level isolation is better. And for the cases where you don't need isolation, you might as well go full serverless.
Not at all. We simply didn’t want to upgrade, test and redeploy 100+ applications every time a developer wanted to use the latest JVM on just one of them. It made the upgrade process much more incremental, predictable and safer than if we just upgraded JVMs for everyone all at once.
> You can download jars from 25 years ago and run them on today's JVM no problem
Yeah but you may not be able to compile the source code for them. Especially if you have old code that uses things like xjc or SOAP.
EDIT: Quekid5 below points out that this wasn’t true for Java 8->11 upgrades, and it was actually the desire to upgrade to 11 and to get on the faster Java release train that really made Docker images our deployment system of choice.
> I actually think the way forward in the long term is unikernels.
On this we appear to agree, which is why I mentioned firecracker in my original post:
> These days I tend to think that something like Firecracker is more likely to be a solution to deployment problems than Docker is, but I haven't tried it yet...
No, you don't. You might not even have to install Docker, e.g. Podman will probably do just fine. "All" docker is doing is calling some kernel code to set up namespaces, etc.
With very few exceptions the only thing you might have to worry about is the kernel version, but given Linux's historical compatibility story there and the fact that the JVM doesn't really rely on any esoteric kernel features, you'll also be fine there.
With the JVM the changes around modularization from 8->11 were hugely distruptive such that you couldn't just run any old 8 program on 11, so you couldn't upgrade the JVM unless all the JVM-based stuff running on the server was upgraded in one go, etc. etc.
That said, Docker networking… :(