Gone are the days of building a VM from scratch, following instructions for a previous version of the OS, installing 10 dependencies, installing the app, cursing when it fails half way through, installing another missing dependency, installing the app again, bouncing the server, and then having it all fall apart again because the app isn't registered to run as a service at startup (because you missed that step).
All of this was possible before Docker through Vagrantfiles and the like but Docker made it much cleaner and significantly less resource intensive (i.e. no longer need a VM per item).
With Vagrant, I still need to figure out how to install e.g. Postgres, or Redis, or whatever, into the Vagrant VM (usually using salt/chef/ansible/etc.), or—much more rarely, because this isn't "idiomatic"—I'll find a Vagrantfile for someone else's virtual Postgres appliance VM. Which I then need to integrate into my virtual-network architecture as its own separate VM with its own lifecycle management et al.
With Docker, my app's image just depends on the postgres:9.6 Docker image, and so when I start my app, a copy of Postgres is downloaded and started as well. My app "owns" this container: the config management for what version of Postgres is running is done by my app (just like a library dependency), rather than the resulting container being thought of as a separate "piece" of my system to be managed by the ops team. The ops team manages my service, which contains Postgres as a component. Same as if I had built a VM that contained both my app and Postgres.
In short, containers (and especially the higher-level abstraction of container "services" or "pods") allow you to build and plan your service as a set of separate black-boxes, rather than owning their build processes; but then allow you to run your service as a unit and upgrade it as a unit, rather than each build-time component resulting in a separate runtime consideration.
---
And yes, all this could be accomplished just as well with VMs. There's nothing specifically about containers that makes them able to do things that VMs cannot. It's just how the two ecosystems have evolved.
If you:
• built an equivalent of Docker's "public registry" and "private URL-accessible registries" for VMs—maybe by generalizing AWS's AMI registry
• ensured that all common VM software could start VMs using a spec that pointed at an AMI URN/URL, downloading and caching AMIs from wherever in the process
• encouraged a public stance toward having a Vagrantfile in your project root that will—with no configuration—build a public-usable virtual appliance out of your project
• added automatic-build-from-Vagrantfile support to your public AMI registry
• encouraged an 'immutable infrastructure' approach to the resulting Vagrant VMs, such that they'd put all their state into hypervisor-provided stateful mounts (of SAN disks or NFS or what-have-you)
• enforced a common semantics for services/pods of VMs in hypervisors
...then you could treat VMs the way you treat containers, using the VM-management client tooling to push out a version-upgrade of your service, that would replace various VMs with VMs based on a newer AMI—without losing any state.
It's all a matter of changing the culture and idioms. That doesn't mean it's easy.
But for every time I see someone using actual configuration management and best practices for reproducible Docker architecture, I see a hundred times when there are brittle and convoluted shell scripts or worse, entire application definitions in a 500+ line Dockerfile (which is neither configuration management nor scripts. At least the scripts are somewhat more portable and maintainable!)
If you don't have to specify the dependencies or the build process to the user, then you can get away with the build process not being well defined. Docker is a win for 'easy installation', but I wonder if it degrades the quality of projects which rely on it?
Weird, You wouldn't have to deal with Nginx and services for local development
What you describe doesn't sound like local development... But rather acceptance/manual integration or product/feature review/approval
But in places with good automation there's tools or a pipeline that automatically spins up instances (potentially containers) with your branch/feature and automatically link them to other services and exposes them
From this point of view, docker can be useful for deployments... But it's mostly useless for development, since it doesn't help with keeping prod/Dev environments identical to each other
> ...
> But it's mostly useless for development, since it doesn't help with keeping prod/Dev environments identical to each other
If you're working on a feature that integrates with LDAP, you need an LDAP accessible locally. Docker lets you spin one up near instantly. The alternative I'm describing is to install the LDAP server locally or in a VM. Both are definitely options, but they're significantly more intrusive or involve (or both).
Ditto for a Postgres DB, a Redis server, or any other external resource needed by your app. It's not just for integration tests. You need them available to develop against and Docker provides a consistent way for everybody to spin up those resources quickly.
Vagrant can mimic multiple OSs while containers are stuck to host os - What am I missing?
"Docker docker Docker? Docker. Docker docker docker docker Docker docker docker. Docker, Docker docker Docker docker Docker."
Now the hype seems to be wearing off and people are realizing that it's just a way of treating Linux installs like giant static binaries plus a whole lot of unnecessary complexity.
"Docker is fantastic! You can run anything you want, easily. Except, uh, don't try to run a database or anything like that. Oh and here are a dozen different flow charts and tables explaining how to handle networking. And uh make sure you still do all of the same VM provisioning for security since containers don't give you any. Simple!"
Linux container technology, by which I mean the Linux kernel APIs used by Kubernetes, CoreOS rkt, and Docker, do not have an opinion about whether the processes that run as containers are ephemeral or persistent. Containers can be just as persistent as the host they're running on.
For example, consider a Linux distribution using systemd. Systemd might launch regular processes upon system startup, and it might also launch containers where both types of processes are equally persistent on the parent host. See the documentation for systemd-nspawn [1] and machinectl [2]. The Arch Linux wiki has more details about how to use that distribution with nspawn [3]. Containers managed in this way are just like other system processes aside from being containerized.
[1] https://www.freedesktop.org/software/systemd/man/systemd-nsp...
[2] https://www.freedesktop.org/software/systemd/man/machinectl....
Containers seem really great for running inside schedulers in order to squeeze every last bit of performance out your servers while also making it easy to move things around as needed. To me this is things like app servers, web servers, load balancers, queue workers, microservices, etc.
I don't think of a database needing to be moved around, and I want its performance profile to have room for growth when needed (in other words, give me the beefiest server and only run the DB on it). Also, a database doesn't generally have 15 dependencies you have to hand compile/install like many apps do.
There seems to be a lot of operational complexity with doing things like "ok, here's our database, but the data is not in the container, and if the DB does move, we have to take the data with it." How long does the move take? Wouldn't it be better to just have another DB standing by to swap in immediately?
I guess my point is (and I'm actually, genuinely asking as someone who hasn't spent much time in the container world): what operational benefit does having a DB in a container give?
I develop different PHP apps - some are, uh, fossilized and don't work with MySQL 5.7 or later, some are on a more modern stack and can work with the latest and greatest stuff. Other apps I am working on run on pgsql. Also, I am on OS X.
All of this means it's either a Vagrant VM which I always forget to shut down and breaks every couple of months instead of Docker where I can do a simple docker ps -aq|xargs docker stop, and everything is pretty much reproducible.
And no, running the DBs native on OS X is a pure PITA - good luck getting different versions of MySQL and PHP to peacefully coexist.
On production servers the story is different but I can tailor a production server environment to the exact specs the software requires.
Makes me think of stali [0], the static linux distro that avoids all dynamic linking.
[0] https://sta.li/
Containers allow you to run almost all of the past decades of software with no or little modification (and most modifications are done in bash), a unikernel is more like a new OS that applications need to be ported to, without the full POSIX API (eg, no subprocesses) - it's probably easier to port a multiprocess server (eg most SMTP servers) from Linux to the NT API than to port them to a unikernel
A JEE application doesn't care if WebSphere is running on OS XYZ, bare metal or an hypervisor.
In a way I consider POSIX C's runtime that should have been made part of ANSI C.
After all we on Java world were already doing that with application containers, it would be just a matter of running them bare metal.