Containers, Docker, and Kubernetes

~22 min

Engineering teams have long encountered a frustrating sentence: “it works on my machine.”

An application may work perfectly on a developer’s laptop but fail when it reaches a test server or production environment.

The code may be identical, but the surrounding environment is not.

One machine may have a different operating-system version, a different programming-language runtime, an outdated library, a missing package, a different configuration, a different system tool, or conflicting dependencies.

The application does not run in isolation. It depends on an entire surrounding environment.

Containers help package that environment into a more consistent and portable unit.

The shipping-container analogy

Before standardized shipping containers, cargo arrived in many different shapes and sizes, and each port needed specialized processes for loading barrels, boxes, sacks, machinery, and other loose goods.

Standardized steel containers changed global shipping.

Cargo could be packed into a uniform box, and ships, trains, trucks, and cranes could move that box without needing to understand every item inside it.

Software containers use a similar idea.

A Concept · lights on your mapcontainerA package holding an application with much of what it needs to run (runtime, libraries, dependencies, files, startup command) in a standardized, isolated format. Shares the host OS kernel, making it lighter than a VM. The answer to “it works on my machine.” packages an application with much of what it needs to run in a standardized format.

The infrastructure does not need to understand the application’s individual files and dependencies, but it does need to know how to run the container.

A useful mental model is: package the application once, then run the same packaged unit in several environments.

What is inside a container?

A container commonly includes application code, a programming-language runtime, libraries, packages, system tools, required files, and a defined startup command.

For example, a containerized Python application might include the coffee backend code, Python 3.13, the installed Python packages, required operating-system libraries, and the startup command.

Because the team defines these pieces together, the application no longer depends on whatever happens to be installed on the machine, and the hidden differences between a developer’s laptop, a test environment, and production shrink.

What containers do not include

A container generally does not package an entire physical computer.

And it does not usually contain its own independent operating-system kernel. The kernel is the core of an operating system, the part that talks directly to the hardware and supervises every running program. Containers running on one host commonly share the host’s kernel.

Containers versus virtual machines

Virtual machines and containers both create isolated environments, but they operate at different levels. A virtual machine behaves like a complete independent computer, with virtual hardware and its own operating-system environment.

A container isolates an application and its dependencies while sharing the host’s kernel.

Virtual machines versus containersLayers
1A virtual machine, simplified:
2Physical machine
3→ hypervisor
4→ virtual machine
5→ complete guest operating system
6→ application
7
8A container, simplified:
9Physical or virtual machine
10→ host operating system
11→ container runtime
12→ several isolated containers

Each container brings its own libraries, files, and tools, everything above the kernel. The kernel underneath is shared.

This usually makes containers lighter than virtual machines. They start faster, are smaller to store, easier to copy, and less resource-intensive. They are also denser, meaning more can run on one machine.

A single virtual machine may run many containers. For example:

One virtual machine, many containersContainers
1One virtual machine
2├── Coffee API container
3├── Receipt worker container
4├── Monitoring container
5└── Internal-tool container

Virtual machines provide machine-level isolation, containers provide application-level packaging and isolation, and modern cloud systems often use both together.

Portability, not magic

Containers make applications more portable. But they do not guarantee perfect behavior everywhere.

The same container may still behave differently because of different CPU architectures, different host-kernel capabilities, or missing configuration. Network restrictions, external-service failures, different stored data, incorrect permissions, limited memory or CPU, and secrets that were not provided can also change how it runs.

For example, a container built for one processor architecture may not run directly on another without a compatible version.

The more accurate promise is: containers make the application environment repeatable and reduce differences between machines.

But they do not remove every environmental dependency.

What is a container image?

A Concept · lights on your mapcontainer imageA packaged, reusable template, built in layers and versioned with tags, containing the files and instructions needed to create a container. Image is to container as program is to process: the frozen definition, and its running instances. is a packaged template containing the files and instructions needed to create a container.

An image may define a base operating-system environment, application code, installed dependencies, environment defaults, exposed network ports, and the command that starts the application.

The image is built before the application runs.

A simplified image definition might say:

  1. Start with a Python environment.
  2. Copy the application code.
  3. Install the required packages.
  4. When started, run the web server.

The result is a reusable artifact from which containers can be created.

Image versus container

The relationship between an image and a container connects to several ideas you already know:

  • In Module 2: program → running process
  • In Lesson 2 of this module: machine type or image → running instance
  • With containers: container image → running container

The image is the defined, reusable package, and the container is one running instance created from it.

A single image can produce many containers:

One image, many containersContainers
1Coffee API image
2├── Running container 1
3├── Running container 2
4├── Running container 3
5└── Running container 4

Each container begins from the same packaged definition but runs as a separate process environment.

Images are built in layers

Container images are commonly built from several reusable layers.

For example: Linux base layer → Python runtime layer → application dependencies layer → coffee backend code layer

If only the application code changes, the build process may reuse the unchanged lower layers.

This can make image builds and downloads more efficient, and the layering helps explain why images can share common foundations without duplicating every byte separately.

You only need to recognize the concept for now: a container image is commonly assembled from reusable filesystem layers.

Image versions and tags

Container images can have versions. A team might build: coffee-api:1.0, coffee-api:1.1, and coffee-api:2.0

The portion after the colon is commonly called a tag.

Tags help teams identify image versions or purposes.

You may also see: coffee-api:latest

latest is a tag like any other. It does not automatically guarantee that the image is the newest, safest, or correct production version.

Production systems often use a precise version or immutable identifier so the deployed code is predictable, which connects directly to Module 3’s lesson on dependency and software versioning.

What is a registry?

A Concept · lights on your mapregistryA warehouse that stores and distributes container images: push images in, pull them during deployment, control access, scan for vulnerabilities. Docker Hub, ECR, and GitHub Container Registry are examples. Like a package registry, but for complete runnable applications. stores and distributes container images.

It acts like a warehouse for packaged applications.

Developers and deployment systems can:

  • Push images into the registry
  • Pull images from the registry
  • Store several versions
  • Control who may access them
  • Scan them for known vulnerabilities
  • Use them during deployments

A simplified workflow is:

  1. Developer changes code
  2. Build container image
  3. Push image to registry
  4. Production pulls image
  5. Production starts containers

The registry plays a role similar to a package registry such as npm or PyPI, and the difference is what is being distributed. A package registry distributes reusable code packages, while a container registry distributes complete runnable application images.

Common container registries

You may encounter names such as:

  • Docker Hub
  • Amazon Elastic Container Registry, or ECR
  • Google Artifact Registry
  • GitHub Container Registry
  • Azure Container Registry

Companies may use public registries, private registries, or both.

A public registry can distribute common base images and open-source software, while a private registry can restrict access to a company’s proprietary application images.

What is Docker?

Concept · lights on your mapDockerThe platform and toolset that made containers widely accessible: define environments, build images, run containers, push and pull from registries. “Dockerize it” = package the app as a container. Containers are broader than one tool; OCI standards keep them compatible. is a platform and collection of tools that helped make containers widely accessible to software teams. Docker allows developers to:

  • Define a container environment
  • Build container images
  • Run containers locally
  • Inspect and stop containers
  • Upload images to registries
  • Download images created by others

Because Docker became so influential, engineers often say: “Dockerize the application.” This generally means: package the application so it can run as a container.

Docker popularized the modern container workflow. But containers are broader than one company or tool.

Container standards

Modern container images and runtimes commonly follow standards maintained by the Open Container Initiative, or OCI.

These standards help different tools agree on how a container image is structured, how a container should be executed, and how tools exchange container artifacts.

This means an image does not always need to be built and run using Docker specifically because other tools can build or execute OCI-compatible containers.

A useful distinction is: Docker is a major container tool and ecosystem. OCI defines common standards that allow container technologies to work together.

What is an artifact?

An Concept · lights on your mapartifactA built, packaged output produced from source code (a container image, a compiled app, a bundled frontend). Source code is what engineers edit; the artifact is the product that gets tested, distributed, and deployed. Pipelines manufacture them in Module 12. is a built, packaged output produced from source code.

Examples include a compiled application, a .jar file, a mobile-app package, a container image, a generated website bundle, and a reusable software library.

Source code is the material engineers edit, and an artifact is the resulting product that can be tested, distributed, or deployed.

For a containerized application: source code → build process → container image artifact → deployment

You will explore how automated pipelines create and deploy artifacts in a later module.

Containers need configuration

A container image should contain the application and its stable dependencies, but it should not contain every piece of environment-specific information.

The same image may run in development, testing, staging, and production, and each environment may need different database addresses, API endpoints, feature settings, log levels, credentials, and resource limits.

These values are commonly supplied as configuration when the container starts.

The goal is: same application image, different controlled configuration.

This avoids building completely different code packages for every environment.

Containers and secrets

Passwords, API keys, and database credentials should generally not be permanently embedded inside a container image.

Because anyone who can retrieve the image might be able to inspect its files and layers, sensitive values should instead be provided through protected secrets-management systems when the container runs.

For example, the container image holds the application code and dependencies, while the database password, the payment API key, and the signing secret are provided as runtime secrets.

The image can then be widely distributed within the company. It contains no permanent credentials.

You will explore secrets-management systems later in this module.

Containers and persistent data

Containers are commonly designed to be replaceable.

If a container crashes, the platform may delete it and create a new one, which means important data should not depend solely on the container’s temporary local filesystem.

The coffee API container should not be the only place storing customer orders.

Persistent information should live in systems such as databases, object storage, persistent storage volumes, external caches, and message queues.

The container runs the application logic, and persistent services hold the lasting state.

A useful principle is: containers should be disposable. Important data should not be.

Running one container

Running one container is relatively straightforward. A developer can start a container on a laptop or VM and expose a network port.

For example: coffee API container → listens for requests → connects to database → returns responses

But production applications rarely run only one container forever.

They may need many copies of the same container, automatic restarts, traffic distribution, scaling, and deployment across several machines, along with health monitoring, configuration management, secrets, and persistent storage.

Coordinating all of those containers requires another layer of software.

What is container orchestration?

Container orchestration is the automated management of containers across a group of machines.

An orchestrator may decide:

  • Which machine should run each container
  • How many copies should run
  • What happens when one crashes
  • How requests reach healthy containers
  • When more copies should be created
  • How containers receive configuration
  • How new application versions are deployed
  • How storage and networking are connected

The word orchestration suggests many separate parts coordinated into one system.

What is Kubernetes?

Recognition — just know it existsKubernetesA widely used open-source container-orchestration platform (K8s): schedules workloads across a cluster, restarts failures, maintains the desired number of copies, rolls out new versions. Powerful and famously complex; not every workload needs it. is a widely used open-source container-orchestration platform.

The name is often shortened to K8s, the 8 representing the eight letters between the K and s in “Kubernetes.”

Kubernetes manages containerized workloads across a group of machines. It performs the coordination jobs the previous section listed, from scheduling and restarts to traffic distribution and rollouts, and it can also roll a failed deployment back to the previous version.

Kubernetes does not replace containers. Instead, it manages where and how containers run.

What is a cluster?

A Recognition — just know it existsclusterA group of machines managed together as one computing environment, the pool an orchestrator schedules workloads onto. is a group of machines managed together as one computing environment.

In Kubernetes, the cluster contains machines that provide capacity for running workloads, and Kubernetes considers the available resources across the cluster as it assigns workloads to appropriate machines.

What is a node?

A machine participating in a Kubernetes cluster is called a Recognition — just know it existsnodeOne machine participating in a cluster: a VM, physical server, or cloud instance providing CPU, memory, and networking for the workloads scheduled onto it..

A node may be a virtual machine, a physical server, or a cloud instance, and each node provides resources such as CPU, memory, networking, and temporary storage.

Kubernetes schedules application workloads onto nodes according to available capacity and configured requirements.

A simplified view is:

Nodes and their workloadsKubernetes
1Cluster
2├── Node A
3│ ├── workload
4│ └── workload
5├── Node B
6│ ├── workload
7│ └── workload
8└── Node C
9 └── workload

Nodes are the machines. The workloads are the application units Kubernetes places on them.

What is a pod?

A Recognition — just know it existspodKubernetes’ smallest deployable unit: one or more containers that run closely together, sharing a network identity. The hierarchy: cluster → nodes → pods → containers. is the smallest deployable unit Kubernetes manages.

A pod contains one or more containers that run closely together, and most application pods hold one primary application container, although a pod can contain supporting containers when they need to share networking or storage closely.

For example:

A podKubernetes
1Coffee API pod
2├── Coffee API container
3└── Logging helper container

The containers inside a pod share certain resources, including a network identity.

A useful beginner hierarchy is: cluster → nodes → pods → containers → application processes

Kubernetes schedules pods onto nodes, and the containers run inside the pods.

Why not schedule containers directly?

Kubernetes uses pods because some containers need to operate as one tightly connected unit.

For example, one container may run the main application while another provides logging, network proxying, configuration updates, or security support.

The containers can share a pod when they need to communicate through the same local network, share mounted storage, start and stop together, or be scheduled onto the same node.

For beginner purposes, many pods can be imagined as wrappers around one application container.

But the distinction matters: Docker and other runtimes run containers. Kubernetes schedules and manages pods containing those containers.

Kubernetes and desired state

Kubernetes is built around the idea of desired state.

The team might declare:

A desired-state declarationKubernetes
1Run five coffee API pods.
2Each pod needs: 2 CPUs, 4 GB memory.
3Expose them through one service.

Kubernetes compares this desired state with reality.

If one pod crashes (desired: 5, healthy: 4), Kubernetes starts another pod.

If traffic increases and the configuration requests more capacity (desired: 10, healthy: 5), Kubernetes creates additional pods if the cluster has enough resources.

Kubernetes is declarative in this sense. The team describes what should be true, and the system works toward that state.

This is the pets-versus-cattle idea applied to containers.

The system does not preserve one irreplaceable container but the desired number of healthy copies.

Deploying a new version

Suppose the team builds: coffee-api:2.0

Kubernetes can gradually replace pods running the old image with pods running the new image, which is called a rolling deployment or rolling update.

A simplified process is:

  1. Start some version 2 pods
  2. Confirm they are healthy
  3. Stop some version 1 pods
  4. Continue until all use version 2

This allows the application to remain available during deployment, and if the new version fails, the team may roll back to the previous image.

Containers provide the versioned package, and Kubernetes coordinates its operation across the cluster.

Kubernetes is powerful — and complex

Kubernetes solves difficult problems, but it introduces its own vocabulary, configuration, and operational work.

Teams may need to understand:

  • Pods
  • Deployments
  • Services
  • Ingress
  • Nodes
  • Namespaces
  • Secrets
  • Storage
  • Scaling
  • Resource limits
  • Cluster upgrades
  • Security policies

A small application may not need Kubernetes.

A managed platform, serverless function, or simpler container service may provide enough capability with less operational complexity.

The right question is not “how can we use Kubernetes here?” It is whether this workload and organization need the control and coordination it provides.

Kubernetes can be managed too

A company can install and operate Kubernetes itself.

It can also use a managed Kubernetes service in which a cloud provider operates part of the platform.

Examples include Amazon Elastic Kubernetes Service, or EKS; Google Kubernetes Engine, or GKE; and Azure Kubernetes Service, or AKS.

Even with managed Kubernetes, the customer still manages important areas such as application deployments, container images, permissions, network policies, resource requests, secrets, workload monitoring, and cost.

The shared-responsibility spectrum applies again.

What is Amazon ECS?

Amazon Elastic Container Service, or Amazon ECS, is AWS’s container-orchestration service.

ECS helps teams run and manage containers on AWS infrastructure. It can place containers onto customer-managed EC2 instances or onto provider-managed serverless compute through AWS Fargate.

ECS and Kubernetes solve related problems, but they use different concepts and ecosystems.

ECS is closely integrated with AWS services, while Kubernetes is an open-source platform available across many environments and cloud providers.

Some teams find ECS easier for AWS-focused workloads, and others prefer Kubernetes for its ecosystem, portability, or control.

For recognition purposes: ECS and Kubernetes both coordinate containerized workloads.

What is Fargate?

AWS Fargate is a managed compute option for running containers without directly managing the underlying virtual machines.

With a traditional ECS or Kubernetes setup, the customer may manage a group of EC2 instances that provide the cluster’s compute capacity, while with Fargate the customer specifies the container’s resource needs and AWS supplies the underlying compute.

A simplified spectrum is:

  • EC2: Manage the virtual machine.
  • ECS on EC2: Manage containers and the virtual-machine fleet.
  • ECS with Fargate: Provide containers; AWS manages the underlying compute.

Fargate demonstrates how containers and serverless ideas can overlap.

The customer still manages the application container, but the machines become less visible.

Seeing the full container journey

Imagine that the coffee company updates its backend.

The process might look like:

The full container journeyFlow
1Engineer changes source code
2→ automated build creates a container image
3→ image is stored in a registry
4→ Kubernetes or ECS pulls the image
5→ orchestrator creates running containers
6→ networking sends requests to healthy copies

If one container crashes, the orchestrator detects the failure, stops or removes the unhealthy workload, and starts a replacement from the same image.

If traffic increases, the orchestrator creates more copies, and requests are distributed among them.

The application, no longer tied to one manually configured machine, is defined as a repeatable image and operated as a replaceable group of containers.

The mental model to remember

A container packages an application with its runtime, libraries, dependencies, and required files in an isolated environment.

Containers usually share the host operating system’s kernel, making them lighter than virtual machines.

Docker is a major tool and ecosystem for building and running containers.

The Open Container Initiative, or OCI, defines widely used container standards.

A container image is a reusable packaged template.

A container is a running instance created from that image.

A registry stores and distributes container images.

An artifact is a built output, such as a container image, that can be tested and deployed.

Container orchestration coordinates containers across several machines.

Kubernetes, or K8s, is a widely used container-orchestration platform.

A Kubernetes cluster contains nodes.

Kubernetes schedules pods onto those nodes, and pods contain one or more containers.

Amazon ECS is AWS’s container-orchestration service.

AWS Fargate runs containers without requiring the customer to manage the underlying virtual machines directly.

You should now understand how containers package applications into portable, repeatable units and how orchestration platforms operate those units across groups of machines.

Code now ships in standardized boxes, stored in registries and started wherever capacity is available.

Check — then the lesson continues

An engineer says: “The bug doesn't reproduce locally, but staging and production run the same image, and it happens in both.” What has containerization told them?

▼ answer the check to continue ▼