Chapter 2: Understanding containers and containerized applications
The introduction establishes why understanding containers matters before studying Kubernetes.
After this chapter you will be able to
- Containers and Kubernetes applications. Explain that Kubernetes primarily manages applications running in containers, making a basic understanding of containers useful before exploring Kubernetes.
- Containers as a VM alternative. Explain why giving each application or service its own VM becomes less suitable as the number of deployed instances grows, and why this motivates using containers.
- Shared-kernel container isolation. Explain that containers run application processes in the host operating system and share its kernel, while still giving each process an isolated view of its environment. Contrast this with VMs, which run separate guest operating systems and kernels.
- Resource and startup advantages. Explain why containers generally use fewer resources and start applications faster than VMs: they do not need another operating system’s processes to run or boot.
- Shared-kernel security tradeoff. Describe why container isolation is weaker than VM isolation and how an unlimited container’s memory use can affect other containers.
- Docker images registries and containers. Distinguish a container image, an image registry, and a running container by describing what each contains or does.
- Image distribution and consistent files. Trace how a developer builds an image, shares it through a registry, and runs it on another Docker-enabled computer; explain why the application sees consistent files.
- Copy-on-write container changes. Describe how read-only image layers and a per-container writable layer keep file changes isolated, including what deletion does.
- Host compatibility limits. Explain why having Docker installed does not guarantee that an image will run correctly on every computer.
- Running an image. Explain how docker run uses an image and a command to start a container, and distinguish an explicitly supplied command from an image's default command.
- Container run sequence. Trace what the Docker CLI and daemon do after docker run, through image retrieval, command execution, and container shutdown.
- Image tags and caching. Explain how image tags select versions or variants, what an omitted tag means, and why latest does not guarantee a fresh download on every run.
- OCI Image and Runtime Standards. Distinguish the OCI Image Format Specification from the OCI Runtime Specification and state what each standardizes.
- Kubernetes Runtime Choice. Explain how the Container Runtime Interface lets Kubernetes use runtimes other than Docker, and why a Docker-built image can run with another OCI-compliant runtime.
- Kiada application components. Describe what Kiada offers and how its Node.js web application, client-side JavaScript, and Quote and Quiz services work together in HTML mode.
- Server-side text response flow. Distinguish who calls the Quote and Quiz services in the HTML and plain-text modes, and explain the resulting internal and external access requirement.
- Dockerfile instructions and base image. Explain how this Dockerfile packages Kiada and why it starts from a Node.js base image.
- Build command and context. Describe what the image name and tag option and the final dot mean in the Docker build command, and where the completed image is stored.
- Docker daemon build process. Trace how the Docker CLI, build context, and daemon participate in building the image.
- Image layers and file deletion. Explain how Dockerfile directives contribute layers to this image, how to inspect them, and why deleting a file in a later layer does not remove it from an earlier one.
- Container launch and access. Explain how the Kiada container runs in the background and how mapping host port 1234 to container port 8080 makes the application accessible.
- Docker Hub image tagging. Explain why the locally built image needs a Docker Hub-compatible tag and what adding that tag does to the image.
- Registry push and remote use. Describe how the section makes a locally available image usable on another computer.
- Container stopping and resuming. Explain how Docker stops a container and why a stopped container can be started again.
- Container deletion and image retention. Distinguish deleting a container from stopping it, including what happens to the container image.
- Namespace-Based Process Isolation. Explain how Linux namespaces change what a container process can see and use, and why this can make it appear to run in its own operating system.
- Dedicated Container Network Interfaces. Trace how a network namespace can give a containerized process its own visible set of network interfaces.
- Selective Namespace Sharing. Explain how two processes can share some resources while retaining separate views of others.
- Shell access to running containers. Describe how running a shell as an additional process in an existing container lets you inspect the environment the application sees, and explain what the -i and -t options provide.
- Container process visibility and IDs. Explain why a process list inside the container excludes host and other-container processes, while the host can see the container’s processes under different IDs.
- Isolated container filesystem view. Describe what appears when you browse the container’s root directory and why the host’s files are not visible there.
- Namespaces versus cgroups. Distinguish restricting which resources a process can access from limiting how much it can consume, and explain why cgroups matter for containers.
- Docker CPU and memory limits. Describe how Docker options constrain a container’s CPU cores, CPU time, or memory, and state what enforces those limits.
- Shared kernel isolation limits. Explain why containers remain a security risk even when namespaces separate their environments and cgroups limit their resources.
- Privileged container risks. Distinguish ordinary containers from privileged containers and explain when the section says privileged containers should be used.
- Capabilities and least privilege. Explain how capabilities offer a narrower alternative to a fully privileged container and how to choose them.
Section by section
Introduction
The introduction establishes why understanding containers matters before studying Kubernetes.
- Containers and Kubernetes applications: Explain that Kubernetes primarily manages applications running in containers, making a basic understanding of containers useful before exploring Kubernetes.
Why it matters: This connection explains why the book introduces containers before deploying applications on Kubernetes.
Key terms: Kubernetes, containers
2.1 Introducing containers
This section explains why running each microservice in its own VM becomes costly and difficult to manage at scale, motivating containers as an alternative.
- Containers as a VM alternative: Explain why giving each application or service its own VM becomes less suitable as the number of deployed instances grows, and why this motivates using containers.
Why it matters: This explains the scaling problem that makes containers worth introducing.
Key terms: microservices, virtual machine (VM), containers, environment requirements
2.1.1 Comparing containers to VMs
This section compares containers with virtual machines in how they share the host, use resources, start applications, and isolate them.
- Shared-kernel container isolation: Explain that containers run application processes in the host operating system and share its kernel, while still giving each process an isolated view of its environment. Contrast this with VMs, which run separate guest operating systems and kernels.
Why it matters: The shared kernel explains both the efficiency of containers and the limits of their isolation. - Resource and startup advantages: Explain why containers generally use fewer resources and start applications faster than VMs: they do not need another operating system’s processes to run or boot.
Why it matters: This is why a host can often run more separately packaged applications as containers than as VMs. - One application per container: Justify the section’s recommendation to run one application per container rather than grouping several applications in it.
Why it matters: This convention makes containerized applications easier to manage with the tools used later in the book. - Shared-kernel security tradeoff: Describe why container isolation is weaker than VM isolation and how an unlimited container’s memory use can affect other containers.
Why it matters: The efficiency of sharing a host does not provide the same separation as running applications in different VMs.
Key terms: container, host OS, kernel, VM, guest OS, isolation, overhead, system processes, start-up time, application
2.1.2 Introducing the Docker container platform
Explains how Docker packages, distributes, and runs applications, why images are portable and efficient, and where that portability has limits.
- Docker images registries and containers: Distinguish a container image, an image registry, and a running container by describing what each contains or does.
Why it matters: These distinctions clarify what you build, what you share, and what actually runs. - Image distribution and consistent files: Trace how a developer builds an image, shares it through a registry, and runs it on another Docker-enabled computer; explain why the application sees consistent files.
Why it matters: The build–push–pull flow explains how the same packaged application moves between computers without depending on their installed libraries. - Reusable image layers: Explain how shared image layers reduce image transfers and storage use.
Why it matters: Layer reuse makes distributing and storing related images more efficient. - Copy-on-write container changes: Describe how read-only image layers and a per-container writable layer keep file changes isolated, including what deletion does.
Why it matters: Copy-on-write explains how containers can share image files without sharing their changes. - Host compatibility limits: Explain why having Docker installed does not guarantee that an image will run correctly on every computer.
Why it matters: The packaged filesystem provides consistency, but it cannot supply every kernel capability or change the host’s CPU architecture.
Key terms: container image, image registry, container, build, push, pull, registry, image layers, shared layers, copy-on-write (CoW)
2.1.3 Installing Docker and running a “Hello, World!” container
This section shows how to run container images with Docker and explains what happens when a container starts, stops, and uses an image tag.
- Docker installation environments: Describe which Docker installation to use on Linux versus macOS or Windows, and where the CLI, daemon, and containers run.
Why it matters: It clarifies where your containers actually run, especially on a Mac or Windows computer. - Running an image: Explain how docker run uses an image and a command to start a container, and distinguish an explicitly supplied command from an image's default command.
Why it matters: The same basic command works for a tiny echo example and for larger packaged applications. - Container run sequence: Trace what the Docker CLI and daemon do after docker run, through image retrieval, command execution, and container shutdown.
Why it matters: It explains both where the image comes from and why the “Hello, World!” container stops immediately. - Image tags and caching: Explain how image tags select versions or variants, what an omitted tag means, and why latest does not guarantee a fresh download on every run.
Why it matters: A tag controls which image you request, but a cached image can affect what a later run actually uses.
Key terms: Docker Engine, Docker Desktop, Docker CLI, Docker daemon, Linux VM, docker run, container image, busybox, Docker Hub, local image cache
2.1.4 Introducing the Open Container Initiative and Docker alternatives
This section explains why Docker is not required for container isolation or for running Docker-built images in Kubernetes, using OCI standards and Kubernetes' Container Runtime Interface.
- Kernel-Based Container Isolation: Explain that Linux kernel mechanisms provide process isolation, while Docker is a tool that uses those mechanisms rather than the source of isolation.
Why it matters: This distinction explains why a container can run without Docker. - OCI Image and Runtime Standards: Distinguish the OCI Image Format Specification from the OCI Runtime Specification and state what each standardizes.
Why it matters: Separate image and runtime standards make it possible to use container tools from different providers. - Kubernetes Runtime Choice: Explain how the Container Runtime Interface lets Kubernetes use runtimes other than Docker, and why a Docker-built image can run with another OCI-compliant runtime.
Why it matters: Building an image with Docker does not require the Kubernetes cluster to use Docker as its runtime.
Key terms: Docker, Linux kernel, process isolation, Open Container Initiative, OCI Image Format Specification, OCI Runtime Specification, Container Runtime Interface, CRI, CRI-O, containerd
2.2 Deploying the Kubernetes in Action Demo Application
Introduces Kiada as the demo application that will be built and run with Docker before being used in later Kubernetes chapters.
2.2.1 Introducing the Kiada Application
Introduces Kiada’s purpose and explains how its HTML and plain-text modes retrieve content through different request paths.
- Kiada application components: Describe what Kiada offers and how its Node.js web application, client-side JavaScript, and Quote and Quiz services work together in HTML mode.
Why it matters: This identifies which parts of Kiada deliver the page and its content. - HTML and text request selection: Explain how a client requests Kiada’s HTML or plain-text version and why the plain-text version is useful from a terminal.
Why it matters: The text response lets you use Kiada without leaving the terminal. - Server-side text response flow: Distinguish who calls the Quote and Quiz services in the HTML and plain-text modes, and explain the resulting internal and external access requirement.
Why it matters: The two response flows impose different networking requirements on the same services.
Key terms: Kiada, Node.js, client-side JavaScript, Quote, Quiz, RESTful services, plain-text mode, curl, /html, /text
2.2.2 Building the application
This section packages an initial version of the Kiada application as a Docker image and explains how Docker builds that image and its layers.
- Initial application and packaging: Describe what the initial Kiada application returns and why the section packages it in a container image rather than requiring a local Node.js installation.
Why it matters: It connects the small example application to the reason for building an image. - Dockerfile instructions and base image: Explain how this Dockerfile packages Kiada and why it starts from a Node.js base image.
Why it matters: The Dockerfile specifies both what goes into the image and how its application starts. - Build command and context: Describe what the image name and tag option and the final dot mean in the Docker build command, and where the completed image is stored.
Why it matters: These command arguments determine which files Docker builds from and how the resulting image is identified. - Docker daemon build process: Trace how the Docker CLI, build context, and daemon participate in building the image.
Why it matters: It explains why the daemon does the work and why extra files in the build directory can slow a build, especially with a remote daemon. - Image layers and file deletion: Explain how Dockerfile directives contribute layers to this image, how to inspect them, and why deleting a file in a later layer does not remove it from an earlier one.
Why it matters: Layer behavior explains both what image history displays and why temporary files should be removed within the same RUN directive that creates them.
Key terms: Kiada, container image, Node.js, Dockerfile, FROM, base image, node:23-alpine, COPY, node app.js, -t
2.2.3 Running the container
This section runs the Kiada container, shows how to access its application, and introduces basic commands for inspecting the container and its logs.
- Container launch and access: Explain how the Kiada container runs in the background and how mapping host port 1234 to container port 8080 makes the application accessible.
Why it matters: It connects the container’s network port to an address you can actually use to test the app. - Running container information: Distinguish the basic running-container information shown by docker ps from the additional information available through docker inspect.
Why it matters: These commands let you confirm that the container is running and look up more details when needed. - Application log retrieval: Explain what application output Docker stores and how to view it with docker logs.
Why it matters: It gives you a way to see what the application has reported while running in the container.
Key terms: kiada-container, kiada image, detached, -d flag, -p 1234:8080, localhost, docker ps, docker inspect, container ID, JSON
2.2.4 Distributing the container image
This section shows how to give a locally built container image a Docker Hub-compatible tag, push it to a registry, and run it on another host.
- Docker Hub image tagging: Explain why the locally built image needs a Docker Hub-compatible tag and what adding that tag does to the image.
Why it matters: The right tag identifies the image for Docker Hub without requiring you to build it again. - Registry push and remote use: Describe how the section makes a locally available image usable on another computer.
Why it matters: A registry lets another host use an image that otherwise exists only on the build computer.
Key terms: Docker Hub ID, tag, image ID, yourid/kiada:0.1, external image registry, Docker Hub, docker login, push, Docker-enabled host
2.2.5 Stopping, resuming, and deleting the container
This section explains how to stop and resume a container, delete a container without deleting its image, and remove unused images.
- Container stopping and resuming: Explain how Docker stops a container and why a stopped container can be started again.
Why it matters: Stopping a container does not mean you must create it again to use it. - Container deletion and image retention: Distinguish deleting a container from stopping it, including what happens to the container image.
Why it matters: The distinction tells you whether you can restart the same container or must create a new one. - Stopped container and image commands: State how to list stopped containers and which commands remove an image or unused images.
Why it matters: These commands let you check what remains and free disk space when images are no longer needed.
Key terms: main process, termination signal, stopped container, docker ps -a, container, container image, state, docker rmi, docker image prune
2.3 Understanding containers
Introduces the upcoming explanation of how Linux kernel features enable process isolation without virtual machines.
2.3.1 Customizing the process environment with Kernel Namespaces
Explains how Linux namespaces give container processes isolated views of system resources while allowing selected resources to be shared.
- Namespace-Based Process Isolation: Explain how Linux namespaces change what a container process can see and use, and why this can make it appear to run in its own operating system.
Why it matters: This explains what provides much of a container’s isolated environment without treating it as a VM. - Resource-Specific Namespace Types: Describe why a process has a namespace for each resource type, using examples of resources isolated by different types.
Why it matters: Separate namespace types make it possible to isolate one kind of resource without necessarily isolating every other kind. - Dedicated Container Network Interfaces: Trace how a network namespace can give a containerized process its own visible set of network interfaces.
Why it matters: The network example makes namespace isolation concrete: the process’s visible interfaces depend on where it runs. - Selective Namespace Sharing: Explain how two processes can share some resources while retaining separate views of others.
Why it matters: It prevents the mistaken assumption that processes must share either their entire environment or none of it.
Key terms: Linux Namespaces, Kernel Namespaces, container, process, Mount namespace, Process ID namespace, Network namespace, UTS namespace, network interfaces, default network namespace
2.3.2 Exploring the environment of a running container
This section shows how to inspect a running container and uses process and filesystem views to illustrate its isolation from the host.
- Shell access to running containers: Describe how running a shell as an additional process in an existing container lets you inspect the environment the application sees, and explain what the -i and -t options provide.
Why it matters: Inspecting what the application actually sees can help you debug a containerized application. - Container process visibility and IDs: Explain why a process list inside the container excludes host and other-container processes, while the host can see the container’s processes under different IDs.
Why it matters: It explains why process listings differ without treating container processes as separate from the host OS. - Isolated container filesystem view: Describe what appears when you browse the container’s root directory and why the host’s files are not visible there.
Why it matters: The filesystem view helps explain both what an application can access and why that separation is useful.
Key terms: sh, Linux namespaces, -i, -t, pseudo terminal (TTY), Process ID namespace, PID, process tree, container’s filesystem, container image
2.3.3 Limiting the resources available to a process using cgroups
This section explains how cgroups limit container resource use and how Docker options set CPU and memory limits that the Linux kernel enforces.
- Namespaces versus cgroups: Distinguish restricting which resources a process can access from limiting how much it can consume, and explain why cgroups matter for containers.
Why it matters: It explains why restricting a container’s view of the host is not enough to prevent resource starvation. - Docker CPU and memory limits: Describe how Docker options constrain a container’s CPU cores, CPU time, or memory, and state what enforces those limits.
Why it matters: It connects the resource limits specified when running a container to the kernel feature that actually applies them.
Key terms: Linux namespaces, Linux Control Groups, cgroups, --cpuset-cpus, --cpus, --memory, Kernel
2.3.4 Strengthening isolation between containers
This section explains why namespaces and cgroups do not fully isolate containers and introduces ways to restrict what container processes can do.
- Shared kernel isolation limits: Explain why containers remain a security risk even when namespaces separate their environments and cgroups limit their resources.
Why it matters: Separate files, networks, and resource limits do not by themselves prevent a container from affecting its neighbors. - Privileged container risks: Distinguish ordinary containers from privileged containers and explain when the section says privileged containers should be used.
Why it matters: Full privileges remove restrictions that help protect the host and neighboring containers. - Capabilities and least privilege: Explain how capabilities offer a narrower alternative to a fully privileged container and how to choose them.
Why it matters: Granting only needed capabilities reduces the access an attacker could exploit. - Seccomp syscall filtering: Describe the fine-grained control over system calls provided by a seccomp profile in this section.
Why it matters: Seccomp lets you restrict individual system calls rather than granting broad access. - SELinux and AppArmor access control: Distinguish the access-control approaches to container hardening briefly described for SELinux and AppArmor.
Why it matters: These mechanisms provide another way to restrict what processes can access.
Key terms: namespaces, cgroups, system kernel, syscalls, elevated privileges, privileged container, syscall, capabilities, drop, principle of least privilege
2.4 Summary
The chapter summary ties together what containers are, how images become running containers, and which Linux features provide isolation.
Where this is used later
- Deploying your application (chapter 3) · Deploying an application on Kubernetes assumes the reader understands that the application runs in a container.
- Organizing containers into pods (chapter 5) · Provides context for organizing application containers into pods.
- Running a local cluster using kind (Kubernetes in Docker) (chapter 3) · Assumes basic familiarity with Docker containers and its CLI.
- Using the built-in Kubernetes cluster in Docker Desktop (chapter 3) · The earlier Docker installation and exercises provide the assumed Docker Desktop setup.
- Exposing pods via services (chapter 11) · The text-mode flow motivates access to services within the cluster.
- Exposing services externally (chapter 11) · The HTML-mode flow motivates exposing services externally.
- Introducing init containers (chapter 5) · The application is built into a container image.
- Creating a cluster using Amazon Elastic Kubernetes Service (chapter 3) · Running and inspecting a container with Docker.
Concepts explained in this chapter
- containerA container is an isolated execution environment that packages an application process with its dependencies while sharing the host operating system kernel.
- container imageA container image is an immutable package containing a container's filesystem, application, and runtime dependencies from which containers can be created.
- DockerDocker is a platform and toolset for building, distributing, and running software containers.
- image layerA container image layer is an independently stored filesystem change that composes a container image and can be shared across images.
- Docker daemonThe Docker daemon is the background service that manages Docker images, containers, and container execution.
- operating system kernelA kernel is the privileged core of an operating system that manages hardware resources and executes system-level operations.
- linux namespaceA Linux namespace is a kernel mechanism that isolates a process's view of selected system resources from processes in other namespaces.
- pid namespaceA PID namespace is a Linux isolation scope that gives processes an isolated view of process identifiers and process hierarchy.
- system callA system call is an interface through which a user-space process requests services or operations from the operating system kernel.
- container registryA container registry is a repository service that stores and distributes container images to authorized clients.
- cgroupA cgroup is a Linux kernel mechanism that groups processes and limits, accounts for, and isolates their use of resources such as CPU, memory, and bandwidth.
- DockerfileA Dockerfile is a text configuration file containing instructions for building a Docker container image.
- copy-on-writeA copy-on-write mechanism preserves shared data until a modification causes a private copy to be created.
- Docker CLIThe Docker CLI is the command-line client for sending container-management commands to Docker.
- Docker DesktopDocker Desktop is a desktop application that packages Docker components and provides a local environment for running containers on supported operating systems.
- image tagAn image tag is a human-readable label appended to a container image name to identify a particular image reference or version.
- Dockerfile instructionA Dockerfile instruction is a declarative command that specifies one step in building a container image.
- base imageA base image is a container image selected as the starting point for building another container image.
- build contextA build context is the set of files and directories supplied to Docker for building a container image.
- UTS namespaceA UTS namespace is a Linux namespace that isolates the system hostname and NIS domain name visible to processes.
- network namespaceA network namespace is a Linux namespace that isolates network interfaces, protocol stacks, ports, and related networking resources.
- hypervisorA hypervisor is software that creates and manages virtual machines by allocating physical hardware resources to them.
- virtual machineA virtual machine is a software-emulated computer that runs an operating system and applications in an isolated environment.
- AppArmorAppArmor is a Linux security mechanism that enforces mandatory access control using path-based profiles for processes.
- Linux capabilityA Linux capability is a fine-grained kernel privilege that grants a process permission to perform selected operations otherwise restricted by kernel checks.
- SELinuxSELinux is a Linux security mechanism that enforces mandatory access control through labels and policy rules.
- seccompseccomp is a Linux kernel security facility that restricts the system calls a process may invoke.
- privileged containerA privileged container is a container whose processes receive unrestricted or nearly unrestricted access to the host kernel's operations.
- microservice architectureA microservice architecture structures an application as multiple independently deployable services that collaborate through defined interfaces.
- file systemA filesystem is a structure and set of operations for organizing, storing, and accessing files, including the isolated filesystem presented to a container.
- entrypoint instructionThe ENTRYPOINT instruction specifies the executable command that runs when a container starts.
- inter-process communication namespaceAn IPC namespace is a Linux isolation scope that separates a process's inter-process communication resources from those of processes outside the namespace.
- mount namespaceA mount namespace is a Linux namespace that isolates the filesystem mount points visible to processes.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
