Cloud
Containers and Kubernetes¶
Containers package an application together with its dependencies so it runs the same way everywhere. Kubernetes runs and coordinates large numbers of containers across many machines. This page introduces both, concept-first, with a few real commands.
Applies to
Any platform that runs containers: a developer laptop, a single Linux server with Docker, or a managed Kubernetes cluster (EKS/AKS/GKE). Examples use docker and kubectl.
What is a container?¶
A container is an isolated, runnable instance of an application and everything it needs (runtime, libraries, config) — but it does not ship its own operating system kernel. Instead it shares the kernel of the host it runs on, using Linux kernel features (namespaces for isolation, cgroups for resource limits) to stay separated from other containers.
That single difference is why containers are so much lighter than virtual machines.
Container vs virtual machine¶
| Container | Virtual machine | |
|---|---|---|
| Isolation boundary | Process-level (kernel namespaces/cgroups) | Hardware-level (hypervisor) |
| Operating system | Shares the host kernel | Runs a full guest OS + kernel |
| Typical size | Tens of MB | Several GB |
| Startup time | Milliseconds to seconds | Tens of seconds to minutes |
| Density per host | Hundreds to thousands | Tens |
| Isolation strength | Strong, but weaker than a VM | Strongest (separate kernels) |
A VM virtualises hardware; a container virtualises the operating system. They are complementary — it is common to run containers inside VMs in production. See Virtualization and Hypervisors for the VM side, and What is the Cloud? for where both fit.
Same kernel, by design
Because containers share the host kernel, a Linux container needs a Linux host. On Windows and macOS, Docker quietly runs a small Linux VM and starts your containers inside it.
Docker basics¶
Docker is the most common tool for building and running containers. Two concepts are central:
| Term | What it is |
|---|---|
| Image | A read-only template — the packaged app + dependencies. Built once, reused many times. |
| Container | A running (or stopped) instance created from an image. You can start many containers from one image. |
Think of the image as the class and the container as the object instance.
Running and inspecting containers¶
# Run nginx in the background, mapping host port 8080 to container port 80
docker run -d --name web -p 8080:80 nginx
# List running containers (add -a to include stopped ones)
docker ps
# List images stored locally
docker images
# View logs and stop/remove the container
docker logs web
docker stop web
docker rm web
docker run will automatically pull the image from a registry if it is not already present locally.
A tiny Dockerfile¶
An image is built from a Dockerfile — a recipe of layered instructions:
# Start from a small official base image
FROM python:3.12-slim
# Set the working directory inside the image
WORKDIR /app
# Copy dependency list first so this layer caches well
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application
COPY . .
# Document the port and define the start command
EXPOSE 8000
CMD ["python", "app.py"]
Build it and run it:
# Build an image named "myapp" from the Dockerfile in the current directory
docker build -t myapp:1.0 .
# Run a container from it
docker run -d -p 8000:8000 myapp:1.0
Registries¶
Images are shared through registries. Docker Hub is the default public registry; cloud providers offer their own (Amazon ECR, Azure Container Registry, Google Artifact Registry), and many teams run a private one.
# Tag and push to a registry
docker tag myapp:1.0 registry.example.com/team/myapp:1.0
docker push registry.example.com/team/myapp:1.0
Why orchestration?¶
One server running a handful of containers is easy. Real systems need much more:
- Many machines. Schedule containers across a fleet and use capacity efficiently.
- Self-healing. Restart crashed containers; replace ones on a dead node.
- Scaling. Run 3 copies today, 30 at peak, automatically.
- Networking & discovery. Give services stable addresses even as containers come and go.
- Rolling updates. Ship a new version with zero downtime, and roll back if it misbehaves.
Doing all of this by hand with docker run does not scale. A container orchestrator automates it — and the de facto standard is Kubernetes.
Kubernetes core concepts¶
Kubernetes (often "k8s") is an open-source orchestrator. You declare the desired state (for example, "run 3 copies of this image"), and Kubernetes continuously works to make reality match.
| Concept | What it is |
|---|---|
| Cluster | The whole system: a control plane plus worker nodes. |
| Node | A single machine (VM or physical) that runs your workloads. |
| Pod | The smallest deployable unit — one or more tightly-coupled containers sharing a network address. |
| Deployment | Declares how many identical pod replicas to run and handles rollouts/self-healing. |
| Service | A stable network endpoint (and load balancer) in front of a set of pods. |
| Namespace | A virtual partition of the cluster for separating teams or environments. |
Pods are usually managed for you
You rarely create pods directly. You create a Deployment, and it creates and maintains the pods. If a pod dies, the Deployment makes a new one.
A minimal kubectl session¶
kubectl is the command-line client for talking to a cluster:
# Show the worker nodes in the cluster
kubectl get nodes
# Show pods in the current namespace
kubectl get pods
# Pods in a specific namespace, with more detail
kubectl get pods -n kube-system -o wide
A tiny Deployment¶
This manifest asks Kubernetes to keep two nginx pods running:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
Apply it and watch Kubernetes create the pods:
# Create or update the resources described in the file
kubectl apply -f deployment.yaml
# Scale to 5 replicas
kubectl scale deployment/web --replicas=5
# Expose the deployment behind a Service
kubectl expose deployment/web --port=80 --type=LoadBalancer
Managed Kubernetes¶
Running the control plane yourself is real work. The major clouds offer managed Kubernetes, where the provider runs and patches the control plane for you:
| Provider | Managed Kubernetes |
|---|---|
| AWS | EKS (Elastic Kubernetes Service) |
| Microsoft Azure | AKS (Azure Kubernetes Service) |
| Google Cloud | GKE (Google Kubernetes Engine) |
See AWS, Azure & GCP Overview for how these fit alongside each provider's other services. For provisioning clusters and infrastructure as code, see Terraform Basics.
Verify your work¶
- [ ] You can explain why a container is lighter than a VM (it shares the host kernel instead of running its own).
- [ ]
docker run -d -p 8080:80 nginxfollowed bydocker psshows a running container;curl http://localhost:8080returns the nginx page. - [ ] You can describe the difference between an image and a container.
- [ ]
kubectl get nodesandkubectl get podsreturn output against a cluster. - [ ] After
kubectl apply -f deployment.yaml,kubectl get podsshows the expected number of replicas, and deleting one pod results in a replacement.
Summary¶
- A container packages an app with its dependencies and shares the host kernel, making it far lighter and faster to start than a VM.
- Docker builds images (from a
Dockerfile) and runs containers from them; images are stored in registries like Docker Hub. - At scale you need an orchestrator for scheduling, self-healing, scaling, networking, and rolling updates.
- Kubernetes does this declaratively, built around clusters, nodes, pods, deployments, services, and namespaces, driven with
kubectl. - EKS, AKS, and GKE are the managed Kubernetes offerings from AWS, Azure, and Google Cloud.