It’s been some 18 months since I looked at Docker and put out a preliminary post on getting started with the container platform. Since then, Docker has moved on leaps and bounds to become an entire ecosystem. In this series of posts I’m going to go back to basics and look at the steps needed to get a practical container application running, including some of the newer features and challenges, such as networking, storage and orchestration. This series will cover a range of container solutions where possible, not just Docker, so expect to see detail on how containers run on Windows and other platforms.
What is a Container?
To understand what containers are requires stepping back to understand how programs and applications are executed by an operating system such as Linux or Windows. Each application consists of one or more processes, grouped in a hierarchy of parent and child processes that together form an application. In fact, all tasks running on an operating system are managed by one process or another, with one ultimate master parent process running as process ID (or PID) #1; for Linux that means the one that was the init process (used for starting and shutting down the system). You can see the active processes on any Linux/Unix system by issuing the ps command; with no arguments the command returns your own processes, with the “-ef” flags as “ps -ef or ps aux” it shows all active processes. On Windows you can see a similar view using Task Manager, or for much more detail, use Process Explorer, a Tool developed by Mark Russinovich, who now works for Microsoft.
A container is a special set of processes that is isolated from other processes running on the host using a feature called namespaces. Namespaces allow containers to see their own view of process IDs, networking, interprocess communication resources and mount points. From the point of view of the container, it sees an isolated view of the world that appears to be a dedicated O/S instance, but exists as just the bare minimum number of processes on the host machine (more on that as we look at the Docker Engine), while using host processes for kernel and other system operations. The container is also mapped to a separate file system that allows each container to see a unique set of files for that instance. The file system is cloned from a master image and uses copy-on-write techniques (a union file system) to track changed files for the container, keeping the storage overhead low (at least for running containers).
Containers Vs Server Virtualisation
If we compare the implementation of containers to virtualisation, the way the two environments work is very different. Hypervisor virtualisation (both type 1 and type 2) effectively emulates device drivers in software for each of the hardware components of a physical machine, including graphics, storage and networking. Each virtual machine is an entire instance of an operating system, including the kernel or other files required to boot the system up. This overhead in storage provides isolation between virtual machines allowing them to be upgraded independently. Whereas with containers the kernel is shared between all containers running on the host. Application code isn’t necessarily shared and can be different depending on the container image being run.
The savings running containers can be quite considerable in terms of disk space, system memory and background processor overhead (like memory management, disk management and application despatching). Containers remove the duplication of running many separate O/S instances, but at the cost of reduced security. For example, Docker currently provides no user namespace isolation. By default containers run with root privilege, or whatever UID has been defined. This is a shared UID across the entire host, so root privilege containers have the ability to modify the filesystem of any volume presented to them. However it’s fair to say that server virtualisation improved in security over time (especially with the addition of virtualisation-specific processor instructions) and containers will do the same.
There are plenty of words written about getting Docker installed, so I’m not going to go over that again. Check out the official installation details in the links at the end of this post. I’m using Ubuntu 15.10 (Wily Werewolf) which runs kernel release 4.2.0. Docker recommends at least version 3.10 of the Linux kernel (whichever operating system you choose) due to the instability of previous releases (for the core container features).
Since the first release of Docker, the ecosystem has expanded and there are now many separate components under development. These include:
- Docker Engine – this is the part of the system that actually manages and runs containers.
- Docker Machine – used to automate the provisioning of containers.
- Docker Hub – a public registry of downloadable images. A registry is divided into repositories of related images.
- Docker Registry – an application that lets you manage your own local images.
- Docker Trusted Registry – a more secure enterprise-class private image repository.
- Docker Swarm – container clustering and scheduling tool, used to (for example) load balance containers across multiple hosts.
- Docker Compose – a tool for creating and building multi-container applications.
- Kitematic – a Mac or Windows-based GUI for managing containers.
Each of the above components form part of the official Docker environment, however there are plenty of other 3rd party tools for orchestrating and managing Docker environments. This will be the subject of another post.
- Docker installation on Ubuntu (official pages)
Comments are always welcome; please read our Comments Policy first. If you have any related links of interest, please feel free to add them as a comment for consideration.
Copyright (c) 2009-2016 – Chris M Evans, first published on https://blog.architecting.it, do not reproduce without permission.