Skip to content

Containerization

A container is an isolated process—or group of processes—running on a host kernel. An image packages a filesystem and runtime configuration; a container is a runtime instance of that image. Containers improve packaging and process isolation, but they are not virtual machines or a security boundary by default.

The Linux Building Blocks

Namespaces

Namespaces give processes different views of system resources:

  • PID: process identifiers and hierarchy;
  • mount: filesystem mount table;
  • network: interfaces, routes, ports, and firewall state;
  • user: user and group ID mappings;
  • UTS: hostname and domain name;
  • IPC: shared memory and message queues;
  • cgroup: resource-control hierarchy view;
  • time: selected clock offsets where supported.

Isolation depends on which namespaces are configured. Processes still share the host kernel.

Control Groups

Control groups account for and limit CPU, memory, process count, and I/O. A memory limit can cause allocation failure or termination; a CPU limit usually throttles. Requests, limits, and application concurrency must agree—giving a process two CPUs does not stop it from creating hundreds of workers.

Filesystems and Layers

OCI images contain immutable filesystem layers plus configuration. A runtime commonly adds a thin writable layer using copy-on-write. Changes in that layer disappear with the container and can copy more data than expected.

Use the writable layer for ephemeral runtime files only. Put durable data in an external service or explicitly managed volume, and verify backup and restore separately.

OCI Standards and Runtimes

The Open Container Initiative defines image, runtime, and distribution specifications. A higher-level engine builds and distributes images, while a runtime prepares isolation and starts the configured process. Products and implementations differ; the portable contract is the image and runtime specification, not one engine's directory layout.

Container Lifecycle

The main process determines the container lifecycle. It must:

  • receive and handle termination signals;
  • stop accepting new work and drain within the deadline;
  • reap child processes when it launches them;
  • write application logs to standard output/error or a deliberate sink;
  • keep mutable state outside the image;
  • return a meaningful exit status.

Avoid wrapping the application in a shell that fails to forward signals. Test real termination, not only startup.

Images

An image should be:

  • reproducible from versioned inputs;
  • minimal enough to reduce transfer and attack surface;
  • immutable and identified by digest for deployment;
  • scanned and patched through rebuilds;
  • labeled with source and revision metadata;
  • built without credentials in its layers or history.

Tags are movable names; digests identify content. A small image is useful, but debuggability and patch policy matter more than chasing the fewest bytes.

Networking

A container receives a network namespace only when configured. Port publishing maps host traffic to a container port; listening inside a container does not automatically expose a service externally.

Names and addresses change. Use service discovery rather than fixed container IPs, bind intentionally, protect management endpoints, and apply network policy as defense in depth—not as a substitute for application authentication.

Containers and Virtual Machines

Property Container Virtual machine
Kernel Shares host kernel Runs a guest kernel
Startup and density Usually lighter Usually heavier
OS flexibility Kernel-compatible workloads Different guest operating systems
Isolation boundary Process and kernel controls Hypervisor boundary

Use VMs, sandboxed runtimes, or dedicated hosts when the threat model requires a stronger boundary. They can also be combined with containers.

Security Baseline

  • run as a non-root user where practical;
  • use user namespaces or rootless operation when supported;
  • drop capabilities and add back only those required;
  • use a read-only root filesystem where possible;
  • avoid privileged mode, host namespaces, device access, and broad socket mounts;
  • apply seccomp and platform security profiles;
  • limit CPU, memory, and process count;
  • mount credentials at runtime with narrow scope and rotation;
  • verify image provenance and continuously rebuild patched bases.

Anyone controlling a container-engine socket may effectively control the host. Treat it as a privileged administrative interface.

Operational Checklist

  • Does the process handle signals and shutdown correctly?
  • Are resource limits compatible with runtime settings?
  • Is all durable state external and recoverable?
  • Are images immutable, attributable, and free of build secrets?
  • Are privileges, mounts, devices, and network access minimal?
  • Are logs, metrics, health, and exit reasons observable?
  • Is containerization solving a deployment need rather than adding a platform by habit?

See Docker for a practical engine workflow and Kubernetes for orchestration.