A Brief Background
Container or OS-level virtualization implementations in Operating Systems have been around for a while [chroot in Version 7 UNIX (1979), FreeBSD jails (2000), Solaris containers/zones (2005), OpenVZ, Linux containers (~2008) ….].
In Linux (a ubiquitous OS and hence the focus for the remainder of this article), container processes typically use OS kernel features such as control groups (cgroups), namespaces and secure computing (seccomp) to achieve isolation, encapsulation and security. Namespaces limit what processes can see, cgroups limit the resources that processes use and seccomp limits the system calls made by processes to the OS kernel.
In 2013, Docker provided a way of making container implementations on Linux much more easily accessible and leverageable by software developers by providing container images (containing everything that an application needs), container registries and high-level APIs in user space to manage containers, thereby making containerized applications easily packable, portable and deployable.
In 2015, Docker led the way with other companies, to establish the Open Container Initiative (OCI), an open governance structure to standardize the format (image-spec) and runtime (runtime-spec) for containers. Docker contributed significantly to the growth in container usage across organizations and containers started becoming the standard way of running applications.
Soon, there was a greater focus on container security as containers don’t have the same isolation as Virtual Machines. With Linux kernel features such as namespaces and cgroups, there is still a large kernel surface directly exposed to containerized applications and although seccomp reduces the attack surface of the host kernel OS, it is not easy to administer (imagine having to whitelist system calls for various applications). This security concern led to the arrival of sandboxed container implementations such as Google’s gVisor, IBM’s Nabla and OSF’s Kata that focus on better container isolation.
Container: A process that provides an isolated, encapsulated execution environment. Multiple containers (processes) may run on the same host and share the same host OS kernel.
Container Image: A tar file that contains a container root filesystem and a container configuration file. Container images may be “layered” on top of each other using tar files containing differences (additions/modifications/deletions) between consecutively layered images.
Base Container Image: A container image built from scratch. i.e. you want to control everything that goes into the image.
Parent Container Image: A container image on which your container image is based on. You must always use trusted container images as parent container images.
Container Image Builder: Software that builds container images.
Container Registry: A web service repository that stores container images.
Container Storage: Copy-On-Write (COW) union filesystems used to store container images.
Container Runtime: Software that launches a container from a container image. OCI-compliant container runtimes or OCI runtimes are container runtimes that implement the OCI specification.
Container Engine: Software that enables container image building, container registry operations, container orchestrator interaction, unpacking container images and launching container runtimes.