I'll admit it took me a while to realise that Docker containers aren't magical apparatuses that can run software. They are just an OS running like a VM. Yes there's differences but I really wish learning resources began with that.
I think a lot of it has to do with the experts accidentally talking past beginners, missing a lot of the basics before getting into teaching abstractions.
It also reminds me of the feeling I'm experiencing now about learning Elasticsearch. I'm amazed just how few JSON examples I can find online for the API. It was amazing how much it helped for a peer to say, "an index is a table, a document is a record and it's kind of like monogdb."
Furthermore this all reminds me of wrong atomic models in high school. Please just teach me a really simple but wrong explanation then slowly work out the details.
"OS running like a VM" is a wrong summary. Containers are collection of namespaces. Docker manages (starts , stops etc) these containers. It also provides an easy gateway into readymade container images.
I think Waterluvian's point was that _before_ you start talking about things like containers, namespaces, images and so on, you need to explain the basics. Depending on the previous knowledge, your summary may or may not make sense. If you don't know what containers, namespaces or images mean here (basically, you haven't seen docker before), then your summary makes no sense.
If you're a programmer, you most probably have heard about OSes and VMs before, one way or another. Then, the analogy is a bit easier for the beginner to understand. Hence the "slightly wrong but somehow still manages to be a bit informative"-summary Waterluvian gave can teach the beginner the first steps.
Yeah. I'm getting a lot of "no it's not that". And surely this failing is on my end. But I'd learn better with an approach of "yes it's like a VM in these ways. But then it's different in these ways..."
Maybe it's just me. I love teaching and learning by starting with a common but wrong model and learning piece by piece what's different until its an evolved, more accurate model.
So it's an OS though right? Like Ubuntu is running, chugging along like Ubuntu does. And is it sitting on top of some virtual hardware interface to simulate IO?
> And is it sitting on top of some virtual hardware interface to simulate IO?
Not really, no. Software in a container directly talks to the kernel of the host using the normal APIs the kernel provides. A container does not contain a kernel!
No, this is absolutely wrong. Docker containers don't contain a kernel or any init system. They are simply Linux processes that are isolated from each other using a few native features of Linux.
Okay awesome. So then why is my base image called Ubuntu 18.04? It sounds like theres an OS there. That's why I intuitively assemble a model of there being an OS. Not that I'm asking you to explain, but that I wish educational content could start from a common place and explore why it's different.
Different Linux distributions ship with various package managers / other userspace tooling. But they all run on top of the Linux kernel. I can see how having a base image called "Ubuntu 18.04" might make it seem like there's an entire OS running in the container but that's not the case. Check out this Ubuntu base image Dockerfile https://github.com/tianon/docker-brew-ubuntu-core/blob/bcdd3..., you can see that it's throwing a tarball for the root filesystem into the container (and some Docker-specific stuff), nothing crazy.
Ubuntu is just a collection of software. The most important piece of software in that collection is the Linux kernel.
That kernel is what is shared between different containers. You can have 5 copies of Ubuntu (or Debian, or Mint) in separate containers, but they're all using the same kernel. This is what makes containers much more efficient than multiple full VMs.
In your example, the docker image makes a certain presumption - the presumption is that the OS that the host is going to run is Ubuntu-ish and 18.x generation-ish and probably runs on a 64bit amd_64. So unless your code is very complicated, then probably by pulling Ubuntu 18.04 libraries and setting some linker rules things are going to work on most systems.
Still most images are based on distros because it's so convenient. Apart from software written in Go that is usually shipped as images based on "scratch". I think there should be simpler building blocks for assembling images thatn complete distro images. For instance when you create an Nginx image it could just contain the Nginx binaries and the libraries they are linked with.
It's an exactly correct summary from a user's point of view and the fact that everyone says it's wrong is just confusing people. Virtual Machine is a concept and doesn't have or require a technical definition. The fact that Docker doesn't require a hypervisor is completely irrelevant to everyone who isn't working the core Docker platform. Containers provide a layer of indirection that imitates a completely separate and distinct operating system on top of a host OS. That's a VM to the eyes every developer who just needs to run Linux operations from OSX or Windows.
The distinction is relevant to me for the simple reason that I can run “top” from a normal shell and see what’s going on in all my containers, attach debuggers to them, etc.
To confuse things even further, Docker on OSX and Windows actually does use a fully-fledged VM that the containers run on.
Truly understanding the Linux kernel namespacing features that Docker is built on certainly takes more effort to learn, but I disagree that it's irrelevant to anyone not working at Docker. Understanding your tools makes you a better developer, and allows you to understand what is and isn't possible.
I think it is a fair summary, because the implications of running in Docker are often the same as running a real VM.
To exemplify, a common mistake is to run a server as the entrypoint of the docker container. The server will then run as PID 1, with all the implications and responsibilities an init process has. This causes a lot of subtile and annoying problems.
Well, not if you use Docker on Windows or Mac. But these are technicalities that don't matter that much.
Unless you are writing kernel drivers or you need to tweak certain kernel parameters, running in a Docker container is very much as running in a VM. With the same responsibilities, e.g., setting up an init process.
My point is that most people don’t even really know that’s how a VM works. They just think of a VM as a fresh sandbox where they can install and run stuff without deleting somebody else’s files or programs.
I'm hearing a repeated theme in your comments that people don't know much about how anything works, and that's supposedly OK. That's actually not OK. :)
No, that's how learning curves work. Until we can Matrix beam info into our skulljack, humans will spend a notrivial amount of time having to make do with using things while not fully understanding how they work.
Unless one is 31337-rockstar-ninja-IQ150-programmer, the uptake of new skills is painful and takes time. The pedagogical process is important. It's totally OK to not know how anything works as long as you acknowledge that and are willing to learn.
I totally agree. That wasn’t the sentiment I was responding to, which sounded more like “nobody knows how that works, and they don’t really need to, so why are you wasting their time explaining how it actually works?”
It is never a good idea to not understand what you're doing, especially when the boundaries of who does what are moving around.
I'm mostly an ops person in outlook, although I was a programmer for over a decade and write my share of code. The software-ization of infra is a good thing; unlike some ops folks, I don't find it threatening, I find it cool.
What I find dismaying is some of the horrific stuff I catch before it gets to production, and what I do find threatening in a different way is worrying about what I miss.
Moving OS-level dependency management in to dockerfiles? Great! How are you scanning that against CVEs? If you don't know you're not running a different kernel, I have a sneaking suspicion you're... not. And so on down the list of traditional ops practices I frequently discover developers had no idea even happened.
There is nowhere in the docker-noob's workflow where the huge distinction between a docker container instance and a super light VM actually matters.
Source: I knew nearly nothing about docker a year ago. And now I'm one of my company's go-to people for docker questions. The pain is still fresh in my mind and I see noob-pain every day :)
Why not correct the misinformation then? Docker is nothing like a VM. It uses cgroups to reserve resources like CPU, memory, etc, and namespaces to isolate containers and their respective processes. VM applications will have to emulate hardware, so the kernel running under VM is able to enumerate hardware devices. Virtual machine emulates a computer with a full ISA.
You are describing the specific technical details about how Docker containers are implemented. The analogy to VMs comes from the observation that VMs virtualize the hardware while containers virtualize the operating system.
> The analogy to VMs comes from the observation that VMs virtualize the hardware while containers virtualize the operating system.
Aaaand that off-the-cuff statement clears up the difference between them that I've been missing for months. Containers really do just look like a VM, if you don't know the implementation details and are just using them.
I wouldn't describe it this way if your goal is to correct misinformation. VMs can definitely pass through real hardware instead of emulation. (most often used for GPUs and network cards) And docker containers can use emulated hardware. (from the app's point of view) Normal processes can run emulated hardware via user-mode linux.
The idea of a VM is so messy these days, it's best to define what kind of VM are you talking about first. (language? system? foreign hardware?)
You are hopelessly out of date. VMs are not Xen with emulation. Neither are they the original VMware. Nor are they QEMU without acceleration.
VMs are qemu-system-x86_64 -machine accel=kvm or whatever is the platform specific way to run a VM under a hypervisor. This has been the case since hypervisors showed up on the scene, aka right after what was the predecessor of Virtuozzo
Xen was never an emulator. That's technically incorrect. Not does the definition of VM change because of hardware acceleration. That's also technically incorrect.
It should have been VMware with emulation, not Xen. You are correct
The overhead of running a VM absolutely changes depending on whether it is a type 1 hypervisor or a type 2 hypervisor or if the runner/monitor supports acceleration.
You can run a VM with QEMU without accel=kvm and it will be dog slow. Try it.
If we were just talking about namespaces alone, I'd agree. As it's commonly used, though, Docker containers often contain a whole distro userspace too. (But sure, you're typically only starting one process with the container.)
Except they feel for all intents and purposes like tiny VMs.
If I gave a pre-Docker era engineer two terminals, one host, one in a container, they'd probably quickly figure out they are on the same physical machine. But unless they were super savvy at some very specific stuff, they'd probably conclude it was just a VM.
Every dev I've introduced to docker workflows basically treat it like a vm. The only ones that didn't already had experience with cgroups/chroot and related tools.
It's honestly better to think of Docker as "VM, but actually you use the same kernel" than "processes that are isolated".
Other poster compared it to electron models. Yes, "balls in orbits" is wrong, but kids are already familiar with planetary orbits, and that mental model works until basically Organic Chem II.
1. For software, open source or not, that is driven by a commercial company, it is often not in their best interest to tell people what it actually is, that they are selling. They care more about conversion rates than educating. E.g. notice how the docker.com website doesn't seem to explain at all what these "Docker containers" are, instead throw around phrases the marketing department came up with: "Docker is the de facto developer standard for building and sharing apps that enable simplicity, agility and choice [...]".
Doesn't mean the tech is good or bad. It can just make it obnoxious to sift trough the propaganda to get the info you want/need.
2. There are plenty of developers that can't be bothered to obtain a deeper understanding of the things they are working with, beyond the getting started tutorial. Which is fine in the beginning, but eventually one should get past that.
For a less cynical view that says pretty much the same: They want to tell people what's the software usef for / what do they gain from using the software, and not internal details.
Would you prefer to know what docker containers are, or what they provide? For example would you rather the first explanation started "Containers allow you to run applications in an environment with its own filesystem and network, isolated from the resources of the main system", or "Containers are a standardised abstraction layer over linux namespaces and resource use restrictions, with common interfaces for network and volume management"? And would you stop using containers if they provided the same benefits, but technically in a different way?
Docker is bad because while docker images crudely compose sequentially (the fs layers), docker files don't compose at all.
The goal of Nix and Nixpkgs is to have effient recipes for building everything ever, in all configurations. The docker ecosystem could never get there.
Now containers do make sense for deployment, but that has little to do with docker, as those docker replacements for kubernetes demonstrate.
> The goal of Nix and Nixpkgs is to have effient recipes for building everything ever, in all configurations. The docker ecosystem could never get there.
Packaging is just one component of a container, and it actually works quite well in docker, since it feels like you’re packaging up the entire OS.
These kind of poor examples lead to a huge amount of waste when using Docker because people learning it are not taught about how layers interact, leading to ridiculous things like 'COPY' followed by 'RUN chown'.
Layers are a _core_ part of how Docker works, why not make this example "correct" by doing:
> RUN apk --no-cache add chromium chromium-chromedriver
Then just a comment like this: "it's important to group layers if possible to reduce your image size. By using `--no-cache` apk will update at the same time as installing".
This article also has an image that shows containers running “on top of” docker; that’s not how any of this works. Docker is just the daemon that sets up the namespaces and runs the containers. It’s not some
magical runtime, any more than “iptables” is. It just talks to the kernel.
I think this post is attempting to oversimplify, and is doing a bad job of teaching in the process.
Running Docker containers is definitely on top of the Docker runtime. Maybe not from a PID parent point of view, but absolutely from an abstraction point of view.
Try doing anything hardware-network-topology relevant stuff without `network=host`, like running a ROS cluster with direct ethernet connections between hosts and cameras.
It's definitely "on top" in a way bare-metal isn't. Same way that a vm is "on top of" kvm even though the cpu supports hardware virtualization.
Nvidia-docker is another abstraction. It's a pass-through. It's not the same as bare-metal. Certainly feels the same 98% of the time, but in that 2% it is very much apparent there is a layer in between.
The article is a “what is docker?” and This is a perfectly fine way to use docker. There’s always room for optimizing layers in the future. Always start with the basics rather than overwhelming people with details.
The point I was making is why the following snippet doesn't make your image smaller _is the basics_:
> RUN echo something > some_file
> RUN rm some_file
Neglecting to even mention it leads to issues down the line because people don't get the fundamentals. There are a lot more confusing things than this when working with Docker.
Small images is one component of optimizing a container. I disagree that a small image is fundamental. In fact I’d say it’s largely a small optimization detail that has very little real world impact.
Really nobody really cares about container sizes except for their own efficiency. We run thousands of containers. Many of them tens of GB. They could all be optimized to a small size but it really doesn’t matter and is not worth the engineering time most of the time.
It's not necessary about the size, and nor is it always a premature/useless optimization. It's about knowing how layers interact which is important. And not hard to teach either.
And yes, if you're adding 5+ GB to each image build through something silly like a 'RUN chown' it's worth fixing. Maybe not complex refactoring, sure, but we are talking about the basics here.
I think their point is that for most use cases, large images don't have a sizeable real world impact. They're more expensive to move around, and you can only fit so many large, distinct layers on a single machine, but a moderately sized organization will barely notice the cost.
They do have a sizeable real world impact. Moderately sized organizations usually build and store the images in a public cloud, which in turn do not provide any straightforward registry cleaning capabilities (at least I didn't find any in AWS or GCP). This leads to hundreds and thousands of gigabytes being wasted and money being flushed down the drain. Not to mention that network traffic in public clouds can quickly rack up the bill as well.
This Docker and Kubernetes hype and the fact that few people understand and care to implement these technologies correctly fills Amazon's and Google's pockets with money that could be spent elsewhere.
It’s like having a “What is sorting?” article with bubblesort as the algorithm of focus. It’s easy to explain and answers the question. Yes, time complexity is fundamental to designing algorithms but it’s not something necessary for an introductory article.
> It's not necessary about the size, and nor is it always a premature/useless optimization. It's about knowing how layers interact which is important. And not hard to teach either.
Learning layers is not critical to get up and running with Docker. You can learn it easily afterwards, but on the very first introduction it's just unnecessary cruft that distracts you from your goal.
More importantly, you can actually use Docker in daily practical applications your whole life not caring about layers. Think about it: why should you care about layers if you don't care about build size or build time?
At this stage, caring for layers is just premature optimization.
Each layer is a write only operation. So if you `RUN some_build.sh` and then `RUN rm junk`, you basically do nothing to reduce the final image size. So you see a lot of like `RUN some_build.sh && rm -rf junk`. There's some overhead with each layer as well.
Nowadays docker server, when run with the experimental flag, allows you to build images with the `--squash` option, so your whole image will contain a single layer.
Alternatively you can use buildah [1] to build your images via a script, but you'll lose the cache docker puts in place.
Thanks a lot for the feedback. I believe simplicity at this phase of learning is much more valuable than efficiency, that's why I haven't tried to produce the most efficient images as examples. Since your suggestion also simplifies the Dockerfile itself, I have replaced the previous one with your suggestion, thanks!
You do realize that bad habits tend to not die, right? Don't teach bad practices because you're targeting newbies...teach them the best practices from the start.
Agreed, I didn't mean to teach bad practices to anyone, I am just trying to put simplicity in front of efficiency so that people can grasp the technology better and benefit from that.
That is more the fault of docker than the user. Docker should be smart enough to spot files that exist transiently only for a few layers in a final image, and then maybe decide to never store those intermediate layers (always regenerating them on demand, or storing them only in some less-permanent form)
This has to be one of the dumbest statements I've ever read about docker.
I admit some people definitely abuse the usage of Docker, because of their bad copy/paste practices from basic step-by-step walk-throughs. But the thing that makes docker great is it's easy of use to create reproducible deployments. And if you don't want to use a projects docker images; a projects Dockerfile is still a great reference on how to get a project deployed on a linux platform.
Also, any Dockerfile that downloads something that might be updated (especially package managers, but also any wget/curl/... that doesn't check against a hardcoded hash) isn't reproducible at all.
Recently somebody showed me their sophisticated Docker file that was supposed to build a Maven project "in a reproducible way". When you ran it it spent 5 minutes downloading a bazillion files from the internet…no prior information on the content of those files was on the system. If the content of version X of a dependency changed in the meantime, you'd never know.
The post emphasize that docker (or its proper name, a container) provide weaker isolation compare to VM but I wish author can expand on this topic a little bit.
Also I'm disappointed that the good old chroot is not mentioned, or the BSD jail system.
The title was promising but it seems that the author hasn't noticed that Docker the company uses the same name for many different things. On Mac and Windows, Docker is a VM. On Linux it's what this article discusses. I don't even know what Docker Enterprise is.
On Windows most people will be using a VM to run Linux in which will then be used to run containers. It’s more correct to say that Docker runs inside a VM on Windows (and on MacOS).
On Windows it is also possible to run Windows containers (no Linux at all) that use the Windows kernel and run Windows programs.
Hey, OP here, thanks a lot for the input. I know that the company uses the same name for multiple stuff, but I also think that, from my very own experience, people associate the name "Docker" with containers in general, regardless of the runtime used with them; therefore, I wanted to come up with an explanation that is simple enough to get started with containers, and decorate it with some examples to make things more approachable for beginners. I believe that there are certain improvements that containers might bring to software development lifecycle of certain products, and I wanted to enable people to attempt improving their workflows with this article.
If you have suggestions to improve my point above in the article itself I'd be glad to take that input and incorporate it into the article itself, feel free to write here or reach out to me via email in my bio. Again, thank you for the feedback.
> therefore, you will be externalizing these values and decouple them from the application, which will give you great flexibility in the long term
I think this is one of the worst "Best Practices" ideas that are parroted by people who haven't thought deeply about the issue. It's really a bad legacy from the era when most software was actually distributed. Now that most software runs in environments that are controlled by the same organization that developed the software, the principle is far less valuable.
Nowadays, most software should have most of its configuration information - paths, DB URLs, HTTP endpoints, etc - hard-coded into it. This strategy follows the "convention over configuration" philosophy, and it gives you a range of benefits. First of all, you can run tests on your config to make sure everything is working properly (check various files are present, do a SELECT * LIMIT 1 from DB tables, etc). You can catch config errors at compile time, eg by using enums like prod/dev/qa to represent environment names. And it prompts you to apply a refactoring mindset to your config - when you notice that your config code is repeating itself extensively, you'll realize this and be able to take steps to refactor, standardize, and simplify the config.
I'm not entirely sure if this is what GP was describing, but as a quick example, likely any that use the Django web framework. By default it puts the settings inside the repo, and at least at my work we just build off of that by putting multiple settings files in the repo and switch between them depending on dev/beta/live/etc.
I have a SQL library that I maintain and it supports Postgres, Maria, MySQL and SQLite. I use Docker for integration testing and it works really well. I have no need for these db engines otherwise, so making them just completely go away when not working on the library is excellent.
I'm currently working on implementing Docker support for a multi tenant service where users can login to their IDE from a Chromebook or what not... It seems docker was not designed for that use case. And every tutorial out there assumes you are running as root and have the Docker daemon installed on your local system...
> The actual way containers work is a complex topic that I will not get into here, but overall the concept is simple: give me an operating system (OS) level virtualization so that I can play around with different stuff in isolation.
Sad to see he gave up before he started, and instead of explaining what Docker is, went off into the docker and docker-compose CLI commands. What an opaque explanation too :(
Docker is hard to explain, and the official documentation won't help you understand it. I'm sad that so few people are self aware enough to combine just the right, minimal depth of concepts about kernels, operating systems, systemd, namespaces, and the fact this all only works on Linux, to make a truly approachable explanation. Most developers are really bad at teaching, they only describe things they already know, vs actually trying to teach something.
Docker runs on Windows. Windows containers run on Windows. Linux containers run on Linux as well as Windows. (To run Linux containers on Windows a small Linux kernel is run inside HyperV.)
You can think of Docker containers as VMs, except instead of running its own copy of the OS it runs directly on top of the host machine's OS.
I understand some bits and pieces about how containers work internally on different platforms, I also have a draft article that goes into depth with these, but the goal of this specific article was to give some general information as a basis for people to get started. You don't have to how namespaces work on Linux in order to build a Dockerfile for your project and share it with your colleagues. You don't have to have the most optimal image in order to replace your `git pull` on your server with a simple Docker Compose setup. My goal was to give high-level overview of these technologies and include actionable examples so that the improvements I believe these technologies bring can be applied immediately by the readers.
> Most developers are really bad at teaching
As per this one, I am honestly sad to read this, though I am glad that you gave this feedback. I had a really hard time a couple of years ago when I was starting to learn these technologies, and I remember very vividly that everything I read was very abstract and lost in detail, which made me feel very dumb. I personally believe that any complex topic can be explained to a layman if the teacher knows the topic well enough, and I wanted to attempt to build a document that I wish existed at the time I was trying to learn these stuff. I was thinking I did a decent job with this article, but clearly there are some short-comings in terms of the content and the way I explained things. If you have any suggestions, please feel free to give suggestions so that I can make improvements to the article and keep it as a living document, I am genuinely interested in improving both my skills and this article itself.
Docker is 1) namespace and chroot for separating processes 2) cgroups to limit hardware resources (CPU/RAM) . This allows for this "packaging" and kind of "sandbox". In addition, it adds a file-saving feature by using a layering filesystem.
I thought Docker is a common standard that defines. How archive format? How build file format? How the config format? What operation system need to support in order to be fully compatible with docker cli?
Instead of a cli tool.
Because there are already standalone docker implementations that implemented with completely different technology. Just like docker on windows (the one runs exe).
Thank you very much for your comment, it made my day. I have had a hard time getting started with these technologies, especially with everyone talking about these without explaining what they actually are in a basic state, that's why I tried to come up with an article that I wish existed when I started. There is probably a lot of stuff to improve there, but I hope it helps getting started with these topics somehow.
120 comments
[ 4.1 ms ] story [ 187 ms ] threadI think a lot of it has to do with the experts accidentally talking past beginners, missing a lot of the basics before getting into teaching abstractions.
It also reminds me of the feeling I'm experiencing now about learning Elasticsearch. I'm amazed just how few JSON examples I can find online for the API. It was amazing how much it helped for a peer to say, "an index is a table, a document is a record and it's kind of like monogdb."
Furthermore this all reminds me of wrong atomic models in high school. Please just teach me a really simple but wrong explanation then slowly work out the details.
If you're a programmer, you most probably have heard about OSes and VMs before, one way or another. Then, the analogy is a bit easier for the beginner to understand. Hence the "slightly wrong but somehow still manages to be a bit informative"-summary Waterluvian gave can teach the beginner the first steps.
Maybe it's just me. I love teaching and learning by starting with a common but wrong model and learning piece by piece what's different until its an evolved, more accurate model.
Not really, no. Software in a container directly talks to the kernel of the host using the normal APIs the kernel provides. A container does not contain a kernel!
Running an Ubuntu user land on top of some generic other Linux kernel will for almost all practical purposes feel the same as running real Ubuntu.
That kernel is what is shared between different containers. You can have 5 copies of Ubuntu (or Debian, or Mint) in separate containers, but they're all using the same kernel. This is what makes containers much more efficient than multiple full VMs.
They are just applications running on top of the very same kernel you would run any application from.
The kernel just provides enough layers of separation on the necessary structures.
There's plenty of material on it; if interested I'd suggest to start to study by kernel namespaces as @mav3rik pointed out.
Truly understanding the Linux kernel namespacing features that Docker is built on certainly takes more effort to learn, but I disagree that it's irrelevant to anyone not working at Docker. Understanding your tools makes you a better developer, and allows you to understand what is and isn't possible.
I think it is a fair summary, because the implications of running in Docker are often the same as running a real VM.
To exemplify, a common mistake is to run a server as the entrypoint of the docker container. The server will then run as PID 1, with all the implications and responsibilities an init process has. This causes a lot of subtile and annoying problems.
Unless you are writing kernel drivers or you need to tweak certain kernel parameters, running in a Docker container is very much as running in a VM. With the same responsibilities, e.g., setting up an init process.
This is exactly what Docker containers AREN'T.
Don't think of containers like tiny VMs. Think of them as processes with additional isolation from each other.
Under the hood they are simply a process isolated with namespaces, but their behavior on the outside feels like getting a VM.
Unless one is 31337-rockstar-ninja-IQ150-programmer, the uptake of new skills is painful and takes time. The pedagogical process is important. It's totally OK to not know how anything works as long as you acknowledge that and are willing to learn.
I'm mostly an ops person in outlook, although I was a programmer for over a decade and write my share of code. The software-ization of infra is a good thing; unlike some ops folks, I don't find it threatening, I find it cool.
What I find dismaying is some of the horrific stuff I catch before it gets to production, and what I do find threatening in a different way is worrying about what I miss.
Moving OS-level dependency management in to dockerfiles? Great! How are you scanning that against CVEs? If you don't know you're not running a different kernel, I have a sneaking suspicion you're... not. And so on down the list of traditional ops practices I frequently discover developers had no idea even happened.
There is nowhere in the docker-noob's workflow where the huge distinction between a docker container instance and a super light VM actually matters.
Source: I knew nearly nothing about docker a year ago. And now I'm one of my company's go-to people for docker questions. The pain is still fresh in my mind and I see noob-pain every day :)
Aaaand that off-the-cuff statement clears up the difference between them that I've been missing for months. Containers really do just look like a VM, if you don't know the implementation details and are just using them.
You probably didn’t mean that they literally emulate an instruction set, because most modern hypervisors don’t emulate most instructions.
The idea of a VM is so messy these days, it's best to define what kind of VM are you talking about first. (language? system? foreign hardware?)
That's true, but as VMs also isolate processes from each other, this can confuse others. Let's be more exact:
A VM = isolated kernel and userspace.
- Advantages: security
- Disadvantages: speed
A container = isolated userspace only. Shared kernel.
- Advantages: speed, size
- Disadvantages: security
Both can have pre-created images to avoid the problem of recreating workspace. Docker did not invent orchestration.
Nuh? Of starting, sure. Of running? A margin of error.
- Containers in this case: userspace on kernel on hardware
- VMs in this case: userspace on kernel on virtual hardware on kernel on hardware.
There are very fast VMs (the Firecracker MIcroVM) but they're not in popular use.
VMs are qemu-system-x86_64 -machine accel=kvm or whatever is the platform specific way to run a VM under a hypervisor. This has been the case since hypervisors showed up on the scene, aka right after what was the predecessor of Virtuozzo
The overhead of running a VM absolutely changes depending on whether it is a type 1 hypervisor or a type 2 hypervisor or if the runner/monitor supports acceleration.
You can run a VM with QEMU without accel=kvm and it will be dog slow. Try it.
For CPU/memory, yes.
For network, possibly (lots of iptables re-writes)
for disk, not so much, docker(depending on what driver you have) suffers from write amplification.
If I gave a pre-Docker era engineer two terminals, one host, one in a container, they'd probably quickly figure out they are on the same physical machine. But unless they were super savvy at some very specific stuff, they'd probably conclude it was just a VM.
Every dev I've introduced to docker workflows basically treat it like a vm. The only ones that didn't already had experience with cgroups/chroot and related tools.
It's honestly better to think of Docker as "VM, but actually you use the same kernel" than "processes that are isolated".
Other poster compared it to electron models. Yes, "balls in orbits" is wrong, but kids are already familiar with planetary orbits, and that mental model works until basically Organic Chem II.
1. For software, open source or not, that is driven by a commercial company, it is often not in their best interest to tell people what it actually is, that they are selling. They care more about conversion rates than educating. E.g. notice how the docker.com website doesn't seem to explain at all what these "Docker containers" are, instead throw around phrases the marketing department came up with: "Docker is the de facto developer standard for building and sharing apps that enable simplicity, agility and choice [...]".
Doesn't mean the tech is good or bad. It can just make it obnoxious to sift trough the propaganda to get the info you want/need.
2. There are plenty of developers that can't be bothered to obtain a deeper understanding of the things they are working with, beyond the getting started tutorial. Which is fine in the beginning, but eventually one should get past that.
You're right. It's only slightly better than zombo.com (https://html5zombo.com/)
Would you prefer to know what docker containers are, or what they provide? For example would you rather the first explanation started "Containers allow you to run applications in an environment with its own filesystem and network, isolated from the resources of the main system", or "Containers are a standardised abstraction layer over linux namespaces and resource use restrictions, with common interfaces for network and volume management"? And would you stop using containers if they provided the same benefits, but technically in a different way?
The goal of Nix and Nixpkgs is to have effient recipes for building everything ever, in all configurations. The docker ecosystem could never get there.
Now containers do make sense for deployment, but that has little to do with docker, as those docker replacements for kubernetes demonstrate.
Packaging is just one component of a container, and it actually works quite well in docker, since it feels like you’re packaging up the entire OS.
> RUN apk update
> RUN apk add chromium chromium-chromedriver
These kind of poor examples lead to a huge amount of waste when using Docker because people learning it are not taught about how layers interact, leading to ridiculous things like 'COPY' followed by 'RUN chown'.
Layers are a _core_ part of how Docker works, why not make this example "correct" by doing:
> RUN apk --no-cache add chromium chromium-chromedriver
Then just a comment like this: "it's important to group layers if possible to reduce your image size. By using `--no-cache` apk will update at the same time as installing".
I think this post is attempting to oversimplify, and is doing a bad job of teaching in the process.
Try doing anything hardware-network-topology relevant stuff without `network=host`, like running a ROS cluster with direct ethernet connections between hosts and cameras.
It's definitely "on top" in a way bare-metal isn't. Same way that a vm is "on top of" kvm even though the cpu supports hardware virtualization.
Nvidia-docker is another abstraction. It's a pass-through. It's not the same as bare-metal. Certainly feels the same 98% of the time, but in that 2% it is very much apparent there is a layer in between.
> RUN echo something > some_file
> RUN rm some_file
Neglecting to even mention it leads to issues down the line because people don't get the fundamentals. There are a lot more confusing things than this when working with Docker.
Really nobody really cares about container sizes except for their own efficiency. We run thousands of containers. Many of them tens of GB. They could all be optimized to a small size but it really doesn’t matter and is not worth the engineering time most of the time.
And yes, if you're adding 5+ GB to each image build through something silly like a 'RUN chown' it's worth fixing. Maybe not complex refactoring, sure, but we are talking about the basics here.
This Docker and Kubernetes hype and the fact that few people understand and care to implement these technologies correctly fills Amazon's and Google's pockets with money that could be spent elsewhere.
Learning layers is not critical to get up and running with Docker. You can learn it easily afterwards, but on the very first introduction it's just unnecessary cruft that distracts you from your goal.
More importantly, you can actually use Docker in daily practical applications your whole life not caring about layers. Think about it: why should you care about layers if you don't care about build size or build time?
At this stage, caring for layers is just premature optimization.
RUN cmd1 && cmd2 && cmd3 && cmd4
maybe with brackets:
I've not used it but it's on my list to try out, the explicit caching I think ties in with what you're after:
* Requires no elevated privileges or containerd/Docker daemon, making the build process portable.
* Uses a distributed layer cache to improve performance across a build cluster.
* Provides control over generated layers with a new optional keyword #!COMMIT, reducing the number of layers in images.
* Is Docker compatible. Note, the Dockerfile parser in Makisu is opinionated in some scenarios. More details can be found here.
Alternatively you can use buildah [1] to build your images via a script, but you'll lose the cache docker puts in place.
[1] https://buildah.io/
Thanks a lot for the feedback. I believe simplicity at this phase of learning is much more valuable than efficiency, that's why I haven't tried to produce the most efficient images as examples. Since your suggestion also simplifies the Dockerfile itself, I have replaced the previous one with your suggestion, thanks!
I admit some people definitely abuse the usage of Docker, because of their bad copy/paste practices from basic step-by-step walk-throughs. But the thing that makes docker great is it's easy of use to create reproducible deployments. And if you don't want to use a projects docker images; a projects Dockerfile is still a great reference on how to get a project deployed on a linux platform.
you do not. you may also install Podman. Docker does not "own" containers, there is an open standard for containers that any vendor may implement.
Also I'm disappointed that the good old chroot is not mentioned, or the BSD jail system.
On Windows it is also possible to run Windows containers (no Linux at all) that use the Windows kernel and run Windows programs.
If you have suggestions to improve my point above in the article itself I'd be glad to take that input and incorporate it into the article itself, feel free to write here or reach out to me via email in my bio. Again, thank you for the feedback.
I think this is one of the worst "Best Practices" ideas that are parroted by people who haven't thought deeply about the issue. It's really a bad legacy from the era when most software was actually distributed. Now that most software runs in environments that are controlled by the same organization that developed the software, the principle is far less valuable.
Nowadays, most software should have most of its configuration information - paths, DB URLs, HTTP endpoints, etc - hard-coded into it. This strategy follows the "convention over configuration" philosophy, and it gives you a range of benefits. First of all, you can run tests on your config to make sure everything is working properly (check various files are present, do a SELECT * LIMIT 1 from DB tables, etc). You can catch config errors at compile time, eg by using enums like prod/dev/qa to represent environment names. And it prompts you to apply a refactoring mindset to your config - when you notice that your config code is repeating itself extensively, you'll realize this and be able to take steps to refactor, standardize, and simplify the config.
Do you have references to companies that are developing software this way at scale?
For 99% of the world, the answer is "a file format like .tar.gz except composable".
These guys are really missing their target audience needs by a mile.
My current solution is to give each user their own docker daemon running in a dedicated virtual machine... Do you have a better solution?
Sad to see he gave up before he started, and instead of explaining what Docker is, went off into the docker and docker-compose CLI commands. What an opaque explanation too :(
Docker is hard to explain, and the official documentation won't help you understand it. I'm sad that so few people are self aware enough to combine just the right, minimal depth of concepts about kernels, operating systems, systemd, namespaces, and the fact this all only works on Linux, to make a truly approachable explanation. Most developers are really bad at teaching, they only describe things they already know, vs actually trying to teach something.
Docker runs on Windows. Windows containers run on Windows. Linux containers run on Linux as well as Windows. (To run Linux containers on Windows a small Linux kernel is run inside HyperV.)
You can think of Docker containers as VMs, except instead of running its own copy of the OS it runs directly on top of the host machine's OS.
I understand some bits and pieces about how containers work internally on different platforms, I also have a draft article that goes into depth with these, but the goal of this specific article was to give some general information as a basis for people to get started. You don't have to how namespaces work on Linux in order to build a Dockerfile for your project and share it with your colleagues. You don't have to have the most optimal image in order to replace your `git pull` on your server with a simple Docker Compose setup. My goal was to give high-level overview of these technologies and include actionable examples so that the improvements I believe these technologies bring can be applied immediately by the readers.
> Most developers are really bad at teaching As per this one, I am honestly sad to read this, though I am glad that you gave this feedback. I had a really hard time a couple of years ago when I was starting to learn these technologies, and I remember very vividly that everything I read was very abstract and lost in detail, which made me feel very dumb. I personally believe that any complex topic can be explained to a layman if the teacher knows the topic well enough, and I wanted to attempt to build a document that I wish existed at the time I was trying to learn these stuff. I was thinking I did a decent job with this article, but clearly there are some short-comings in terms of the content and the way I explained things. If you have any suggestions, please feel free to give suggestions so that I can make improvements to the article and keep it as a living document, I am genuinely interested in improving both my skills and this article itself.
Again, thanks a lot for the feedback.
Please watch this awesome presentation: https://www.youtube.com/watch?v=zGw_xKF47T0
Instead of a cli tool.
Because there are already standalone docker implementations that implemented with completely different technology. Just like docker on windows (the one runs exe).