Skip to main content

🐳 Lesson 1: Introduction to Docker

What Docker actually is, why it changed software forever, and the mental model that makes everything else in this course click.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain what a container is, in plain language
  • Describe the difference between containers and virtual machines
  • Articulate the "works on my machine" problem and how Docker solves it
  • Recognize where Docker fits across development, testing, and production

Estimated Time: 30–40 minutes

Prerequisite: None — this is your starting point.

In This Lesson

The Problem Docker Solves

Picture a developer finishing a feature. It runs perfectly on their laptop. They hand it off — and it breaks in testing. It breaks again in production. It breaks on a teammate's machine. The dreaded refrain follows: "but it works on my machine!"

Why does this happen? Software doesn't run in a vacuum. It depends on a specific version of a language runtime, particular libraries, environment variables, operating-system packages, and configuration. When any one of those differs between two machines, behavior differs. Reproducing an environment by hand is slow and error-prone.

graph TD A["Without Docker"] --> B["Works on my machine"] B --> C["Fails in testing"] B --> D["Different in production"] B --> E["Breaks on a teammate's laptop"] F["With Docker"] --> G["Runs in a container"] G --> H["Same container everywhere"] H --> I["Testing ✓"] H --> J["Production ✓"] H --> K["Teammate ✓"] style A fill:#fecaca,color:#1e293b style F fill:#bbf7d0,color:#1e293b

Docker's core idea: package your application together with everything it needs to run — code, runtime, libraries, and configuration — into a single, standardized unit called a container. That container then runs the same way on any machine with a container runtime. The environment travels with the app.

📖 Definition

Container: a lightweight, isolated, runnable package that bundles an application with its dependencies, so it runs consistently across different computing environments.

Containers vs Virtual Machines

People often confuse containers with virtual machines (VMs). Both isolate workloads, but they do it at very different levels. An analogy: a virtual machine is a separate house — its own foundation, plumbing, and walls. A container is an apartment in a shared building — it has its own private space, but shares the building's foundation and utilities.

Virtual machines each bundle a full guest OS, while containers share the host OS kernel Virtual Machines Each app carries a full guest OS Guest OS Bins / Libs App A Guest OS Bins / Libs App B Hypervisor Host Operating System + Hardware Docker Containers Apps share one host OS kernel Bins/Libs App A Bins/Libs App B Bins/Libs App C Docker Engine Host Operating System (shared kernel) Hardware
Figure 1: A VM virtualizes hardware and runs a full guest OS per app; a container shares the host kernel and bundles only what the app needs.

Because containers skip the per-app guest OS, they are dramatically lighter:

AspectVirtual MachineContainer
Isolation levelFull OS, virtualized hardwareProcess-level, shared kernel
SizeGigabytesMegabytes
Startup timeSeconds to minutesMilliseconds to seconds
Overhead per appA whole guest OSJust the app + its libs
Density (per host)A handfulDozens to hundreds
⚠️ Note: Containers and VMs are not enemies — they're complementary. In the cloud you'll often run many containers inside a VM, combining the strong isolation of VMs with the efficiency of containers.

The Container Mental Model

The shipping-container analogy

Before standardized shipping containers, moving goods was chaos: every item needed custom handling, different trucks, special loading. The steel shipping container changed the world by standardizing the box — any container fits any ship, crane, truck, or train, regardless of what's inside.

Docker does exactly this for software. Your app might be Python, Node, Java, or Go — Docker wraps it in a standard container that any Docker host can run, without caring what's inside.

Traditional deployment needs custom handling per app; Docker standardizes the container Traditional Deployment Custom setup 1 Custom setup 2 Special requirements Different needs per app 😓 Docker Deployment 📦 Container 📦 Container 📦 Container Any host, any platform ✓
Figure 2: Standardize the box, and the same tooling moves every workload.

What "runs anywhere" really means

Think of a coffee-shop franchise. Every location — New York, Tokyo, London — needs the exact same recipe, equipment settings, and process so the coffee tastes identical everywhere. A Docker image is like a "coffee shop in a box": open it anywhere and you get the same result.

The same container image produces identical behavior in every location ☕ app v2.1 ✓ Runtime ✓ Recipe DB ✓ Config New York ☕ app v2.1 ✓ Runtime ✓ Recipe DB ✓ Config Tokyo ☕ app v2.1 ✓ Runtime ✓ Recipe DB ✓ Config London ☕ app v2.1 ✓ Runtime ✓ Recipe DB ✓ Config Mumbai 100% consistent experience, everywhere
Figure 3: One image, identical behavior in every environment.

So a container is best pictured as a lightweight, portable, self-sufficient box. It is:

  • Lightweight — a backpack, not a moving truck
  • Portable — like a USB drive that works on any computer
  • Self-sufficient — a meal kit with every ingredient included
  • Isolated — soundproof rooms in a recording studio
  • Reproducible — a recipe that always yields the same dish

✅ Image vs Container

An image is the blueprint (the recipe); a container is a running instance of that image (the meal you cooked). One image can start many containers. We'll go deep on both in Lesson 2.

Where Docker Fits

The same image flows through your entire pipeline — you build it once and run it everywhere, unchanged.

graph LR A["Your App + Dependencies"] --> B["Docker Image"] B --> C["Developer Laptop"] B --> D["CI / Test Server"] B --> E["Production Cloud"] B --> F["A Teammate's Machine"] style B fill:#bfdbfe,color:#1e293b

The benefits land differently for different roles:

DevelopersOperationsBusiness
No more dependency hellSimple, repeatable deploymentsFaster time to market
Consistent environmentsBetter resource utilizationLower infrastructure costs
Easy collaboration & onboardingEffortless horizontal scalingHigher reliability

Try It Yourself

Enough theory — let's see Docker prove itself. If you've installed Docker (see the setup steps), run:

docker run hello-world

Docker can't find that image locally, so it pulls it from Docker Hub, creates a container from it, and runs it. You'll see something like:

Output:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
Digest: sha256:...
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

In that single command, Docker did four things: the client contacted the daemon, the daemon pulled the image, created a container from it, and streamed its output back to you. That's the whole workflow in miniature — you'll unpack each piece in Lesson 2.

🏋️ Exercise 1: Prove portability to yourself

Objective: Experience "pull once, run anywhere."

Instructions:

  1. Run docker run hello-world and read the output.
  2. Run it a second time. Notice it no longer downloads — the image is cached locally.
  3. Run docker images and find hello-world in the list. Note how tiny it is (~20 kB).
💡 Hint

If you get a permission error on Linux, either add your user to the docker group or prefix commands with sudo.

✅ What you should observe

The first run downloads the image; the second run starts instantly from cache. docker images lists hello-world with a size in kilobytes — a fraction of any virtual machine. That tiny, cached, instantly-runnable unit is the container advantage.

Quick Quiz

Question 1: What is the main difference between a container and a virtual machine?

Question 2: What problem is Docker most famous for solving?

Question 3: What is the relationship between an image and a container?

Summary

🎉 Key Takeaways

  • Containers package an app with everything it needs, so it runs the same everywhere — ending "works on my machine."
  • Containers share the host kernel, making them far lighter and faster to start than virtual machines.
  • An image is the blueprint; a container is a running instance of that image.
  • The same image flows through dev, test, and production unchanged — build once, run anywhere.

📚 Additional Resources

🚀 What's Next?

You understand what Docker is and why it matters. Next, we'll open the hood and see how it works — the engine, the client/daemon split, and how images, containers, networks, and volumes fit together.

🎉 Lesson 1 complete!

You've built the mental model everything else rests on. Onward!