traditional virtualization. Notice that with traditional OS virtualization, each
application runs in its own VM with its own OS instance and all the associated
overhead. However, the application enjoys total isolation from other applications, and
the resources available can be controlled through configuration of the virtual CPU,
memory, and network resources assigned to the VM. With containers, each
application runs in its own container that is isolated at a user-mode level and can have
dependencies on other containers that may contain libraries that are then dependent
on a host OS image (which needs to match the container host OS). Notice that
different containerized applications can be dependent on the same containers or
different containers. This is useful, as some applications may require the same version
of libraries, while other applications may need different versions of libraries,
something that is difficult to achieve traditionally on a shared OS. Control groups
(known as job objects in Windows) enable the grouping of processes. The access to
resources they are allowed to have is a key point of the isolation.
Figure 10.1 Traditional virtualization-hosting applications vs. applications running
in containers
The dependencies between containers are prescribed by the application developer at
the time of the application creation, and the container technology is leveraged
throughout the application’s life cycle. This is achieved by creating a composition file
that specifies the images used and any actions required. (In Docker, this is called a
Docker file, and it is different from a Docker Compose file, as explained at
https://docs.docker.com/compose/compose-file/.) The container images are stored in
a central repository, and when you combine a composition file by using a shared set of
images, the result is immutable. It will always provision and perform the same,
ensuring consistency as it is deployed between environments. This is not the case
when developers normally install “stuff” on their machines, write the code, and then
try to describe the same “stuff” to be installed in QA, then live, and so on. But as an
application developer writes an application to be run in a container, the developer
presses F5 to debug; the container is created, the application is instantiated into it,
and testing is performed. Once development is complete, the application developer
publishes the containerized application either to a public or private repository, which
includes the dependency information related to other containers. The IT operations