All About ContainersChapter 1: Basic concepts
Basic Concepts: Containers, LXC, and Docker
- Namespaces: A concept originally developed by IBM, a Linux namespace wraps a set of system resources and presents them to processes within the namespace, making it look as if they are dedicated to the processes.
- Cgroups: Originally contributed by Google, Cgroups is a Linux kernel concept that governs the isolation and usage of system resources, such as CPU & memory, for a group of processes. For example, if you have an application that is taking up a lot of CPU cycles and memory, such as a scientific computing application, you can put the application in a Cgroup to limit its CPU and memory usage.
Both Namespaces and Cgroups are resource management tools within Linux that help isolate system resources for processes. They together form the foundation of modern-day virtual containers.
What is a container?
Virtual containers have roots in FreeBSD jails and Solaris Zones. But it was Linux Containers – LXC – that helped establishing containers as a virtualization technology suitable for cloud data centers.
LXC is a Linux operating system-level virtualization method for running multiple isolated Linux systems on a single host. The Namespaces and Cgroups features made Linux Containers possible.
Containers decouple applications from operating systems, which means that users can have a clean and minimal Linux operating system and run everything else in some form of containers. Also, because a container offers a convenient unit to encapsulate a small application component, it becomes an infrastructure of choice for building micro-service applications, which enables more manageable application infrastructure and continuous application deliveries. Figure 1 shows a conceptual comparison between a monolithic application and a microservice equivalent that is developed with virtual containers.
Figure 1: Monolithic applications vs. containerized micro-service applications
Docker came along later. Originally it was a project to build single-application LXC containers. Since then, Docker has made several significant advances to the container concept, including moving away from LXC as the container format. Docker containers let users easily deploy, replicate, move, and back up a workload, thus giving cloud-like flexibility to any infrastructure capable of running Docker.
For these reasons, Docker is often credited as the development that led to the modern-day popularity of virtual containers. We’ll discuss why Docker is different from LXC a bit later in this post.
How are containers different from VMs?
Virtual Machines (VMs) virtualize hardware. Every guest VM includes a separate copy of an Operating System on top of the host OS but shares the host’s hardware with other VMs on the same host. Containers, however, virtualize the Operating System – every container has its own CPU, memory, block I/O, network stack and so on, but uses the host’s Operating System as other containers on the same host.
Figure 2 shows the difference between hypervisor-based virtualization versus container virtualization.
Figure 2: VMs vs. containers
In an application environment that has web-scale requirements, containers are an appealing proposition compared to traditional server virtualization with VMs. Another big difference between VMs and containers has to do isolation and security. We will address this issue in the dedicated security discussion of this series
What is Docker?
Docker started out as an open-source project to build specialized LXC but later morphed into its own container runtime environment. At a high level, Docker is a Linux utility that can efficiently create, ship, and run containers. In the next article in this series, we’ll take a more detailed look at Docker containers. Fundamentally, both Docker and LXC containers are user-space lightweight virtualization that uses Cgrops and namespaces to manage resource isolation. There are, however, a number of differences between Docker containers and LXC:
- Single vs. multi-process: Docker restricts containers to running a single process. If your application environment consists of X concurrent processes, Docker wants you to run X containers, each with a distinct process. LXC containers, however, have a conventional init and can run multiple processes.To run a simple multi-tier web application in Docker, you would need a PHP container, an NGNIX container (the web server), maybe a MySQL container (for the database process) and a few data containers for database storage and other application data.The advantages of single-process containers are many, including easy and more granular updates – why shut down the database process when all you want to update is the web server? Also, single-process containers represent an efficient architecture for building micro-service applications.However, single-process containers have their limitations. For instance, you can’t run agents, logging scripts, or a secure shell (SSH) daemon inside the container.
- Stateless vs. stateful: Docker containers are designed to be stateless, more so than LXC. Docker does not support persistent storage; it gets around this by allowing users to mount host storage onto containers as “Docker volumes.” Because the volumes are mounted, they are not really part of the container environment.Also, Docker containers consist of read-only layers; once the container image has been created, it does not change. In runtime, if the process in a container makes changes to its internal state, a “diff” is made of the internal state as well as of the image from which the container was created. If you delete the container, the diff disappears, but if you run “docker commit,” the “diff” becomes part of a new image – not the original image, but a new image, from which you can create new containers. This is how Docker handles state changes.A stateless container is an interesting entity. You can make updates to a container, but a series of updates will engender a series of new container images, which makes system rollbacks easy to do.
- Portability: This is perhaps the single most important advance made by Docker. Docker abstracts more networking, storage, and OS details from the application than LXC does. With Docker, the application truly is not dependent on configurations of these low-level resources. When you move a Docker container from one Docker-enabled machine to another, Docker provides a guarantee that the environment will be the same for the application.A direct benefit of this approach is that Docker enables developers to set up local development environments that are exactly like a production server. When a developer finishes writing and testing his code, he can wrap it in a container and publish it directly to AWS or a private cloud server; the code will work instantly because the environment is the same.In contrast, with LXC, a developer can get something running on her own machine, but when she deploys it to the server environment, which is usually slightly different from the development environment, she has to spend an enormous amount of time debugging the difference and make the application work for the server environment.Docker took that complexity away. The portability and ease-for-use is the reason why Docker is adopted extensively by developers.
A developer-driven architecture
Decoupling applications from the underlying OS and hardware is the fundamental concept behind virtualization. This enables cloud-like flexibility, including portability and efficient scaling. Containers bring another level of efficiency, portability and deployment flexibility to developers beyond virtualization.
The popularity of containers underscores the fact that this is a developer-driven era. If the cloud was about infrastructure innovation, and mobility was about usability innovation, then containerization is the killer tool, the force-multiplier, for developers.
Our later posts in this series will more deeply explore the developer-driven theme and different aspects of the container ecosystem.
Next Chapter: A Deep Dive into Docker Containers