My VM is lighter (and safer) than your container (2017)
dl.acm.org
dl.acm.org
Docker particularly has always required extra work to run in rootless mode because it was released soon after in March 2013, and for whatever reason it hasn't been a priority to rework the codebase to make that the default. I switched to podman for exactly this reason as my go-to oci implementation and haven't looked back.
The linux kernel features that enable various forms of isolation all require root privileges (CAP_SYS_ADMIN). Once user namespaces were a thing, that allowed you to use user namespaces to get around the root requirements for all the other isolation namespaces.
All of the below still require CAP_SYS_ADMIN:
CLONE_NEWCGROUP: cgroup namespace, for resource control (mem/cpu/block io/devices/network bandwith)
CLONE_NEWIPC: ipc namespace for sysv ipc objects and message queues
CLONE_NEWNET: network namespace, for isolated virtual networking
CLONE_NEWNS: mount namespace, for isolated mounting (filesystems, etc.)
CLONE_NEWPID: pid namespace, for isolated view of running processes
CLONE_NEWUTS: unix timesharing system namespace, for isolation of hostname and domain name
Oh man that is something I've been wanting as well.
As much as I'd love to try this lightweight VM idea, I don't have the time or energy to convert 20+ projects I'm self-hosting into this and then keep everything updated. I'd rather invest this time into learning Docker more and making my existing setup more secure and robust.
Commercially, we leverage Unikraft on kraft.cloud to provide a cloud platform with millisecond semantics.
I came across Unikraft a while ago and went “wow that’s cool, but I have no idea how to use this”, cloud offering and docs you have up there now look amazing! Will 100% be giving this a go first thing tomorrow!!
Kraft Cloud: takes your docker image, and turns it into a “unikernel”, and runs that. In a unikernel, your application _is_ the kernel. There’s no process boundary, no kernel-space/userspace split there’s a single address-space etc.
I believe the idea is that you get a perf benefit-as your application is often the only one running in the container, security is provided by the hupervisor anyways, so may as well cut out all the middle layers that aren’t getting you much. Seems some of the authors/founders of Unikraft are in the comments, they can explain much better than I.
Finally, we also had to design and implement a controller from scratch -- nothing out there provided the millisecond semantics and scalability we needed (plus we also did tweaks to network interface creation and a few other things to get the end to end experience to be fast).
My work had a product that was doing builds and hosting for arbitrary client code, you’re doing all that, plus more. I’ve got massive respect for that, because there were some hard problems to solve, even in our pretty vanilla environment- looks like you guys have done a far better job than we did, plus more!
What really surprised me the most, is how quick and simple it is to compile the linux kernel. Cloned a tag with --depth 1, configured it and then it took ~ 5 minutes to build vmlinuz.bin. As someone who is too young to have had to regularly do that, I had heard multiple stories of how long that's supposed to take but it really doesn't.
I then tried to move from firecracker to qemu microvms but didn't get that far yet since I didn't have more time.
All in all a great learning experience and if I wasn't an undergrad student with no time, I'd love to build a service/business around it.
It used to, but that's why they are only stories now.
The first step should be to not be so entirely reliant on Docker.
Container / VM: I provide isolation where needed, handle safely interacting with outside world, and abstract away all the pesky stuff so programmers can just get stuff done.
I get that a dev machine (OS) isn't usually suitable for deployment or shared development (Container/VM). But seems to me the promise of the Operating System has fallen short, if we are striving to meet so many of the same goals of the OS, with something on the OS that tries to abstract away the OS.
Linux tried to fix that with namespaces and it turned out to be more or less successful, but Linux is not an OS, it's just a kernel, and it's up to real OSs built atop Linux to use namespaces as an implementation detail for real application isolation.
One way to do that is OCI-containers, the other way is Flatpak. Neither of those is not a proper OS yet, but you could call Kubernetes an operating system which uses containers as means for application and resource isolation. Naturally that means Kubernetes is a complex beast, but that's what it takes to provide what users expect from an OS.
Android also comes to mind, they managed to isolate applications between each other quite safely.
If you do not consider Linux with namespaces an OS (because of fragmented userland): Would you then consider FreeBSD with jails or Solaris with zones for fully fledged?
If you still consider those flawed (maybe because thet do not force you into jails/zones) should we at least no consider OS/390 or z/OS as proper operating systems to that/your (not meant inflamatory!) standard?
Yes. Though you do not mention them directly DOS and Windows has ruled the world for years and they opened the door for the nasties. But they were not all there was - only the popular/easy choice. Everything is a trade off.
Raw Linux without userspace could be considered an OS, but it has the ABI only in form of syscalls and the minimal standard FS. That's barely enough for anything other than, say, a statically linked Go binary, which is why it's seldom used by app developers as a target.
To most of your examples I say – yes, that's an OS, and jails or zones have nothing to do with it. Although I'm not familiar with them other than FreeBSD, so I'm relying on your short description and your implied criteria for selecting these examples.
Root isn’t required — look at Podman.
Docker spent so much on marketing, the world is too blind to pivot to a superior alternative!
There has been lot of sharp corners around userns and related tech that needed to get resolved. Notably Debian& Ubuntu disabled unprivileged userns for some legitimate security concerns
> This is a short-term patch. Unprivileged use of CLONE_NEWUSER is certainly an intended feature of user namespaces. However for at least saucy we want to make sure that, if any security issues are found, we have a fail-safe.
from: https://web.archive.org/web/20211022013829/https://kernel.ub...
The virtual machine images are a bit heavier, since you need a kernel and whatnot, but it's negligible at best. The memory footprint of virtual machines with memory deduplication and such means that you get very close to the footprint of containers. You have the cold start issue with microvms, but these days they generally start in less than a couple of hundred milliseconds, not that far off your typical container.
First off, a unikernel is a virtual machine, albeit a pretty specialized one. They're are often based on modular operating systems (e.g., Unikraft), in order to be able to easily pick the OS modules needed for each application, at compile time. You can think of it as a VM that has a say NGINX-specific distro, all the way down to the OS kernel modules.
VMs provide what's called hardware-level isolation, running on top of a hypervisor like KVM, Xen or Hyper-V. Wasm runs higher up the stack, in user-space, and provides what's called language-level isolation (i.e., you could even create a wasm unikernel, that is, a specialized VM that inside runs wasm (eg, see https://docs.kraft.cloud/guides/wazero/). Generally speaking, the higher you go up the stack, the more code you're running and the higher the chances of a vulnerability.
There are also significant operational concerns. With containers you can just have your CI/CD system spit out a new signed image every N days and do fairly seamless A/B rollouts. With VMs that's a lot harder. You may be able to emulate some of this by building some sort of static microvm, but there's a LOT of complexity you'll need to handle (e.g. networking config, OS updates, debugging access) that is going to be some combination of flaky and hard to manage.
I by no means disagree with the security points but people are overstating the case for replacing containers with VMs in these replies.
If you go read the paper this requires a specialized Xen kernel, which in turn requires processor virtualization extensions directly available where you're running these containers. Those extensions aren't generally available if you're already running inside of a VM.
This is a solution that only works on bare metal which I would bet money the vast majority of people using containers, outside of development environments at least, are not running their containers in bare metal but in an existing VM such as on AWS or GCP where this solution is simply a non-starter.
Neat, niche, and doesn't operate in the same world as containers.
That's not really why containers are deployed in VMs, especially in the context of on-prem enterprise software. I think that's more of a legacy issue. For example, for on-prem enterprise software, the enterprise already invested millions into their VM infrastructure so deploying a containerized stack means deploying into their VM infrastructure.
I think when centralized container orchestrators get enough market penetration with properly trained IT, you'll probably see that change.
Also, very few people choose containers for security and isolation. Typically it's for flexibility in deployment, and control of the environment (no more dependency hell).
A container is basically a process restricted by multiple kernel namespace isolation mechanisms. It shares the same kernel with the host and does not present any “virtual hardware”.
examples: a) vm - an entire windows install running in a window on my linux workstation so i can use tax software once a year. two kernels running at the same time. (N+1 for N VMs) b) container - a small python service, its dependencies, and various filesystem bits from alpine-minimal packaged into a file that docker/containerd/whatever can turn into the service running in a little isolated portion of my machine. no matter how many i run, one kernel. the various processes just don't see the host or other procs' files/memory/etc. via namespace trickery (unless there's a security problem, lol)
Your VM is your whole office building and overnight maybe a whole new company can move in but still using the whole building. Your Container is a set of rules, somebody told you when arrived to the reception desk. About where is the only office in the building you can use, plus maybe some common access to shared areas once in a while, like WC and Kitchen. :-)
Seems like you can run state full workloads too.
All processes in a proper OS are already isolated and there is no need for VM.
Container escape exploits are more common than VM escape exploits.
For example GCP and AWS both have container running services. They both use hardware VMs to isolate different tenants. You will never share a kernel with another customer (I don't even think you will share one with yourself by default).
> All processes in a proper OS are already isolated and there is no need for VM.
No. This is not how things work in reality. (Ideally, yes because hypervisors are OS "duct tape" but there is no such readily-available OS with strict resource limits and hard enforced VFS and network isolation.) Isolation, sharing, and hard limits on RAM, CPU, networking, and storage (bandwidth, block devices, and IOPS) is beyond the capabilities of every major OS. This is why VMware and similar type-1 hypervisors exist.
Funnily that's what fly does: take your container uncompress it to a full micro VM and run it on their infra
Firecracker also has containerd support (https://github.com/firecracker-microvm/firecracker-container...).
There are a few ways to run Kubernetes with Firecracker, including FireKube.
(Cold) boot times are determined by a chain of components, including (1) the controller (eg, k8s/Borg), (2) the VMM (Firecracker, QEMU, Cloud Hypervisor), (3) the VM's OS (e.g., Linux, Windows, etc), (4) any initialization of processes, libs, etc and finally (5) the app itself.
With Unikraft we build extremely specialized VMs (unikernels) in order to minimize the overhead of (3) and (4). On KraftCloud, which leverages Unikraft/unikernels, we additionally use a custom controller to optimize (1) and Firecracker to optimize (2). What's left is (5), the app, which hopefully the developers can optimize if needed.
I'm wondering though what value will Kubernetes add beside integrating with existing (presumably Kubernetes-based) infrastructure? At least, this is my understanding of the rationale for Kata containers. Other than that, it seems like it'd be just getting in the way...
If there is some additional isolation required, just run the container in a VM.
i don't think devs care if they use containers or VMs, as long as it's easy and they don't have to worry about which version of Python the host is running
The killer app of Docker isn't the container, it's the depth and uniformity of the UX surrounding the container system. When that is broken by something on the host (non x86 cpu was a major pain for a while before popular images were x-built) and emulation gets in the way and is not as easy, or just mildly different (windows behind corporate firewalls that assign ips used by the docker engine for example), the ease of use falls away for non-power users and it's all painful again.
Tech like Docker for windows and Rancher Desktop and lima has largely matured at this point, but somebody could make a new machine and then the process of gradual improvement starts all over again.
With VMs? You now need a way to get data from within the VM which in most lightweight VM implementations just not possible.
For anyone else wondering how heavy this is on a MacOS, I ran the install script and it just delegated to brew... brew listed the following packages being installed:
==> Fetching dependencies for unikraft/cli/kraftkit: aarch64-elf-binutils, gmp, mpfr, aarch64-elf-gcc, coreutils, gettext, readline, gawk, gnu-sed, pcre2, grep, make, capstone, dtc, mpdecimal, ca-certificates, openssl@3, sqlite, python@3.12, glib, libunistring, libidn2, p11-kit, libnghttp2, unbound, gnutls, jpeg-turbo, libslirp, libssh, libusb, ncurses, snappy, vde, qemu, socat, wget, x86_64-elf-binutils and x86_64-elf-gcc
Most should already exist on your mac if you do development... it seems to rely on qemu, unsurprisingly... openjdk as well (probably to support Java out-of-the-box?), imagegick etc.Took a few minutes to finish installing... the CLI seems to be based on the Docker commands (build, clean, run, 'net create', inspect etc.), some package-manager like commands ('pkg info', 'pkg pull', 'pkg list' etc.), a bunch of "cloud" commands (I suppose that's the non-free part) and "compose" commands just like docker-compose. Interesting stuff.
Note for the parent commenter: the Lua link in the landing page is broken: https://github.com/unikraft/catalog/tree/main/examples/http-...
I tried to run the C hello world example... I get an error, it wants to run Docker?!?! I thought the whole point was to avoid Docker (and containers)??
Here's the log:
i creating ephemeral buildkit container W could not connect to BuildKit client '' is BuildKit running? W W By default, KraftKit will look for a native install which W is located at /run/buildkit/buildkit.sock. Alternatively, you W can run BuildKit in a container (recommended for macOS users) W which you can do by running: W W docker run --rm -d --name buildkit --privileged moby/buildkit:latest W export KRAFTKIT_BUILDKIT_HOST=docker-container://buildkit W W For more usage instructions visit: https://unikraft.org/buildkit W E creating buildkit container: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?: failed to create container
PS. running the hello-world pre-built "image" worked:
> kraft run unikraft.org/helloworld:latest
EDIT:
A lot of stuff looks broken on MacOS.
For example, `kraft menu` doesn't work (error "no choices provided", even though the docs show it working fine without "choices"?)...
`kraft run --elfloader loaders.unikraft.org/strace:latest ./my_binary` also doesn't work (the docs show it working). Error: "unknown flag: --elfloader".
Seems like the product is still in alpha?!
Docker? One line possibly.
VM? Afternoon (unless I want to write ansible too)
For Docker, OrbStack does the same thing as Docker Desktop, Podman Desktop, Rancher Desktop, etc., which is set up a Linux VM running Docker and then present a native socket interface on macOS which relays everything it receives to the Docker socket inside the VM.
macOS doesn't have native capabilities for running containers, which is why the nearest thing you can get to containerd on it requires you to disable SIP so it can use a custom filesystem to emulate bind mounts/null mounts: https://darwin-containers.github.io/
If you read the PRs where the principal author of the Darwin Containers implementation is trying to upstream bits of his work, you'll see containerd comparing his approaches to others and complimenting them by calling them 'the most containerish' because real capabilities aren't there.
(I believe I've read rumors here on HN that Apple has those features internally, fwiw. But they've evidently never released them in a public copy of macOS.)
Another clue in all this is to just run uname in any of your Docker containers in OrbStack; you'll see they're Linux machines. Some operating systems have Linux syscall emulation layers (WSL1, FreeBSD's Linux emulation, Illumos' LX Zones) that could perhaps be used to run Linux containers without hardware emulation or paravirtualization in combination with some native containerization capabilities. Afaik Illumos' LX Zones is the only implementation where that's a supported, intended use case but maybe FreeBSD can do it. At any rate, macOS has never had that kind of syscall compatibility layer for Linux, either. So when you run `uname` in a 'macOS container' and see 'Linux', you can be certain that there's a VM in that stack.
PS: Aside from the fact that it's proprietary, I really do quite like OrbStack. It's the nicest-to-use implementation of something like this that I've tried, including WSL2 and Lima. The fact that it makes the VM machinery so invisible is very much to its credit from a UX perspective!
Once again: Containers are not about isolation or security, they are a package format for shipping applications. The packages are easy to build, distribute, multiarch, ...
And requiring a Linux-VM on macOS to run Linux containers, is not particularly surprising.
Take it up with Apple.
so people use containers instead (even if the container literally only contains a single statically linked binary)
That said, it makes sense from a developer POV; if, during development, you don't need the isolation you can run multiple containers (with on paper fast boot times and minimal overhead) on your development box.
There's plenty of cases to imagine where you need the containerization but not necessarily the isolation.
Anyway containers go quite a bit further than just static linking, most people aren't out there linking all the binaries that their shell script uses together?
Personally, I use containers to quickly spin-up different database servers for development or as an easy way of deployment to a cloud service...
It's not possible to package half a Linux distribution into a single binary. That's why we have containers.
No. Running a container in a VM gets you no additional isolation. Containers share kernel space and as such have limited isolation to VMs, which have isolated kennels. In exchange for this Lack of additional isolation, you’ve added a Bunch of extra Complexity.
Pardon the extra caps I am using iOS voice dictation.
This is similar to how managed container IaaS works. They launch a VM and run your container in it.
It is extra complexity but has a few advantages. 1. People already have a convenient workflow for building container images. 2. The base OS can manage hardware, networking and whatever other low-level needs so that the container doesn't need to have these configurations. 3. If you want to trade of isolation for efficiency you can do this. For example running two instances of a container in the same VM. The container doesn't need any changes to support this setup.
This is the approach we take at kraft.cloud (based on the LF Unikraft project): use Dockerfiles to specify app/filesystem, and at deploy automatically convert to a lightweight VM (unikernel) without the container runtime/layer.
No, you don’t. There is no benefit the container is providing, because The only feature of the container is isolating you from the zero other containers running on the VM.
Using two levels of userland isolation makes about the same sense as using 457 levels of userland isolation.
This paper argues that when you build a extremely minimal kernel (i.e. ditch Linux entirely) and link your application against necessary bits of code to execute _as_ a VM, then you'll get better performance than a container and you'll get that isolation.
This is in fact true based on performance studies, the follow up paper to this shows so: https://arxiv.org/pdf/2104.12721
(Disclosure, co-author of the linked paper.)
We ended up taking this to real workloads if you want to see it in action: https://unikraft.io/
The point of the poster was pretty clear:
“The main benefit is not isolation and security”
It would be nice, but this is really hard to do when modern software has so many layers of crud. Good luck getting say, a PyTorch app, to work doing this without some serious time investment.
The flip side is that if you want something like low-level access to your specific graphics card you may need to implement a lot of additional support. But of course nothing says you have to use this everywhere at the exclusion of everything else. There's plenty of systems in the world that from the kernel point of view are basically "I need TCP" and a whole bunch of compute and nothing else terribly special.
Using the deploy command line tool is the Docker file used to determine dependencies for the hosted VM? What if a developer is using an unusual programming language, like Common Lisp. Is that doable?
The primary benefit is resource usage and orchestration.
Rather than duplicating entire aspects of an OS stack (which might ne considered wasteful) they allow for workloads to share aspects of the system they run on while maintaining a kind of logical isolation.
This allows for more densely packed workloads and more effective use of resources. This is a reason why the tech was developed and pushed by google and adopted by hyperscalers.
But reproducible infrastructure as code is just orthogonal to that: everything from Salt to Nix is credible in that role.
Containerizing on top of a Xen hypervisor never made sense to me.
As someone who made a living doing this at scale, where we would build a new datacenter every 2-4 weeks using 100% open source or off the shelf tools, I completely disagree.
I think PXE booting some servers and running a binary on them is 90% easier than most container orchestration engines, Kubernetes control plane, and all the other problems engineers seem to have invented for themselves. I also think it’s almost always much more performant. Engineers don’t have an intuition to realize that their XXLarge-SuperDuper instance is actually a 5 year old Xeon they’re sharing with 4 other customers. Cloud Prociders obfuscate this as much as possible, and charge a King’s ransom if you want modern, dedicated hardware.
No one will ever be considered for a Nobel over Kubernetes.
If you run a docker build multiple times, and copy a few files into the container, you get a reproducible container image. It is not a hash perfect duplicate, but functionally equivalent.
If builds of your favourite programming language are reproducible or not, is not really related to VM vs. Container.
"Reproducible" is usually defined as "identical output except for the cryptographic signature at the end" (and that should be the only use for a certificate in your build environment, a high-quality build environment should be self-contained and have no network access). That is, once you remove the signature, the built artifacts should be bit-by-bit identical.
It's not a technical matter, it's a human, economical matter and actually... Most people are poor, following the largest scale means following poverty not a good thing.
the articles main point still remains, containers are a slow and bloated answer to this problem.
I concede youll need containers for Kubernetes, and Kubernetes on the surface is a very good idea, but this level of infrastructure automation exists already in things like foreman and openstack. designs like shift-on-stack trade simplicity of traditional hardware for ever byzantine levels of brittle versioned complexity...so ultimately instead of fixing the problem we invoke the god of immutability, destroy and rebuild, and hope the problem fixes itself somehow...its really quite comical.
baremetal rust/python/go with good architecture and CI will absolutely crush container workloads in a fraction of disk, CPU, RAM, and personal frustration.
I really don't understand why people do this: I get having a distaste for containers but some people, seeing the massive success of OCI images, mainly seem content on trying to figure out how to discredit its popularity, rather than trying to understand why it's popular. The former may be good for contrarian Internet forums, but the latter is more practically useful and interesting.
I say this with some level of understanding as I also have a distaste for containers and Docker is not my preferred way to do "hermetic" or "reproducible" (I am a huge Nix proponent.) I want to get past the "actually it was clearly useless from the start" because it wasn't...
Check out https://github.com/jrz/container-shell
It is very useful for managing dependency hell, or at least moving it into "API dependencies" not "Library dependencies", it is handy for pickling a CI/CD release engineering infrastructure.
It's not a security boundary.
(I'm 100% agreeing with parent, in case I sound contentious)
It is a security boundary, just not necessarily the best one.
My comment was more of a soft jab against using containers as the ultimate "thing" for anything and everything. I prefer to use them as "statically linked binaries" for short lived processes (like document building, etc.).
But, whenever someone abuses containers (like adding an HTTPs fronting container in front of anything which can handle HTTPS on its own) I'm displeased.
Relevant XKCD: https://xkcd.com/1988/
The snobbery deployed in this "containers vs. VMs" argument really gets out of hand sometimes. Especially since it's almost never deployed symmetrically. Would you make the same argument against using a BSD jail? Do you refuse to run your services in a separate UID because it's not as secure as a container (or jail, or VM)? Of course not. Pick the tools that match the problem, don't be a zealot.
X86 protected mode, processor rings, user isolation in the multi user operating systems, secure execution environments in X86 and ARM ISAs, kernel and userspace isolation, etc. are purpose built security boundaries.
Virtualization is actually built to allow better utilization of servers, which is built as a "nested protected mode", but had great overhead in the beginning, which has been reduced over generations. Containers are just BSD jails, ported to Linux. This doesn't make containers bad, however. They're a cool tech, but held very wrong in some cases because of laziness.
- https://github.com/firecracker-microvm/firecracker-container...
- https://github.com/kuasar-io/kuasar
- https://github.com/kata-containers/kata-containers
- https://github.com/QuarkContainer/Quark
The isolation could be achieved using namespaces directly. But the API, tooling and registry add a lot of value that would otherwise require a lot of development.
Also last time I looked hypervisors aren't possible on all cloud vendors, unless you have a bare metal server. This matters in my case. Maybe it has changed in the past 3 years.
When docker fits it's great. Same can be said of k8s, where there are a whole bunch of additional benefits.
Swings and roundabouts.