Virtualisation & Containers
Understand virtual machines and containers, and build and run containers with Docker/Podman.
Containers and virtual machines are the foundation of modern deployment. This chapter contrasts the two, then covers building, running, and persisting data with Docker and the daemonless, rootless Podman.
By the end of this chapter you will be able to
- Contrast VMs and containers (isolation vs density).
- Run, inspect, and manage containers.
- Persist data with volumes rather than the container layer.
- Build images from a Dockerfile.
- Apply container security basics (non-root, pinned tags).
14.1 Virtual Machines vs Containers
| VM / Container | |
|---|---|
| Isolation | Full OS + own kernel / Shares the host kernel |
| Size & startup | Gigabytes, seconds-to-minutes / Megabytes, milliseconds |
| Best for | Strong isolation, different OS / Lightweight, fast-scaling apps |
14.2 Running Containers
14.3 Volumes
A container’s own filesystem is temporary — replace the container and the data is gone. Volumes store data outside the container so it survives.
14.4 Building Images
14.5 Guided Lab: Containers End to End
Estimated time: 30 minutes. Run a ready-made container, inspect it, persist data, then build your own image. (Requires Docker or Podman.)
- Run nginx mapped to a host port:
docker run -d -p 8080:80 --name web nginx. - Confirm it serves:
curl -I http://localhost:8080. - Inspect:
docker ps, thendocker logs web. - Run a database with a named volume so data persists (postgres + -v pgdata:/var/lib/postgresql/data).
- Write a minimal Dockerfile for a hello-world app and build it:
docker build -t hello:1.0 .. - Run your image, then clean up:
docker stop web && docker rm web.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| Container exits immediately | Its main process ended or errored. Check docker logs <name>; the CMD may be wrong or a dependency missing. |
| Data gone after redeploy | You wrote to the container layer, not a volume. Mount a named volume at the app’s data path. |
| ‘port is already allocated’ | Another process/container uses that host port. Pick a different host port in -p, or stop the conflicting container. |
| Image huge / slow builds | Use a slim base image, order Dockerfile layers from least- to most-changing, and add a .dockerignore. |
Practice & Prove It
Write-the-command drills
- Run an nginx container detached, mapping host port 8080 to container port 80.
- List all containers, including stopped ones.
- Build an image tagged myapp:1.0 from the Dockerfile in the current directory.
- Show the logs of a container named web.
- Run postgres detached with a named volume pgdata mounted at /var/lib/postgresql/data.
Quick quiz
- How does a container differ from a VM?
- Where should persistent data live?
- What does a Dockerfile define?
- Why avoid the :latest tag in production?
- What security advantage does Podman have by default?
Key Takeaways
- Containers share the host kernel and are tiny and fast; VMs give fuller isolation.
- docker/podman run, ps, logs, stop manage the container lifecycle.
- Persist data in volumes — the container layer is ephemeral.
- A Dockerfile builds a reproducible image; pin versions and run as non-root.
- Containers are the backbone of modern cloud deployment.
Next — Chapter 15: backup and disaster recovery.