Introduction: How Docker Actually Works
In Part 1, you explored what Docker is and why it’s so valuable for modern developers. You learned about containers, images, and how Docker simplifies the mess of inconsistent environments.
Now, let’s lift the curtain and see how it actually works.
When you run a Docker command, who’s doing the work? How does a container get created? Where do images come from — and how does Docker know what to do with them?
In this article, we’ll walk through Docker’s architecture — including the Docker Client, Docker Daemon, and Docker Registry — and then guide you through installing Docker and running your very first real container.
By the end, Docker won’t just be a concept. You’ll have it installed, running, and launching actual software on your machine — with full clarity on what’s happening behind the scenes.
Let’s dive in.
Setting Up Docker
So far, you’ve seen what Docker is, why it matters, and how it solves real pain in modern development. Now it’s time to take the first real step—getting Docker running on your own machine.
You don’t need to build anything just yet. We’ll start by installing Docker, verifying it’s running, and making sure your system is ready for containers. These are quick, foundational steps—after this, you’ll be ready to run your first Docker container.
Installing Docker
To start using Docker, you’ll need to install it on your machine. The setup process depends slightly on your operating system, but Docker has made it easier than ever to get started.
For Windows and macOS
Install Docker Desktop — it’s the all-in-one toolkit that gives you everything you need:
- Docker Engine (the runtime),
- Docker CLI (the command-line interface),
- A clean GUI to manage containers and images.
Download it directly from the official Docker Desktop page.
For Linux
You now have two solid options:
- Docker Desktop for Linux (available for Ubuntu, Debian, Fedora, Arch) — recommended if you want a graphical interface and tooling similar to what macOS/Windows users get.
- Docker Engine via package manager — ideal for CLI-focused workflows or server environments.
💡 Tip: If you’re unsure, start with Docker Desktop. It’s beginner-friendly and integrates seamlessly with the Docker CLI.
System Requirements
Make sure your system meets the minimum requirements before proceeding:
Platform | Requirement |
---|---|
Windows | Windows 10/11 (64-bit), Pro, Enterprise, or Education |
macOS | macOS 10.15 Catalina or newer |
Linux | 64-bit version of Ubuntu, Debian, Fedora, Arch (for Docker Desktop); or compatible server distro for Docker Engine |
If you hit any setup snags — like system permissions or existing software conflicts — the official Docker installation guide has clear, step-by-step help for every OS.
Verifying Your Installation
Once you’ve installed Docker, let’s make sure everything is working correctly.
Open your terminal or command prompt and run:
|
|
You should see output like:
|
|
📝 Note: The version and build number will vary depending on when you install Docker and what version is available at the time. As long as you see a version string and no errors, you’re ready to go.
This confirms that Docker is installed and the CLI is working.
Next, run:
|
|
This will show a full summary of your Docker environment — how many containers and images you have, what version of the engine you’re using, the storage driver, and more.
If both of those commands work without errors, congratulations! 🎉 You’ve got Docker installed and running. You’re ready to take your first real step into containers.
👉 Next: You’ll run your very first container using a single Docker command and see exactly what happens under the hood.
Running Your First Docker Container
You’ve installed Docker — now let’s bring it to life.
In this section, you’ll run your very first Docker container.
No setup. No Dockerfile. No code.
Just one simple command to prove Docker is installed, working, and ready to run real software.
1. Hello from Docker
Let’s start with a quick smoke test that Docker provides out of the box:
|
|
You should see output that ends with something like:
|
|
What just happened?
- Docker looked for a container image called
hello-world
on your machine. - It didn’t find it, so it pulled it from Docker Hub — Docker’s public image registry.
- It created a container from that image.
- The container ran, printed a message, and exited.
✅ This wasn’t just a message. It was a real container that ran on your machine in seconds.
If you saw that “Hello from Docker!” message, congratulations — you’ve just run your first container.
2. Run a Real App: Nginx
Now let’s take it one step further — and run a real web server, again with a single command:
|
|
Here’s what this command does:
-
nginx
is the name of the image we want to run — a popular open-source web server. -
-p 8080:80
tells Docker to make port 80 inside the container available as port 8080 on your computer.That means when Nginx runs inside the container and listens on port 80, you’ll be able to access it from your browser at
http://localhost:8080
. -
-d
runs the container in detached mode, which means it runs in the background, not blocking your terminal.If you don’t use
-d
, the container output will fill your screen and take over your terminal. Running detached keeps things clean.
What just happened?
You started a real Docker container running a full web server. Unlike the hello-world
container, which exited right after printing a message, this one keeps running — until you stop it.
Let’s test that it’s working.
- Open your browser.
- Visit
http://localhost:8080
You should see the default Nginx welcome page.
🎉 Just like that, you’ve got a real web server running — no manual install, no system config, no dependency wrangling. It’s all happening inside a container.
When You’re Done
To stop the container:
- Press
Ctrl+C
if you’re still inside the terminal where you ran the command. - Or use this to stop it by ID:
|
|
You’ve now run two Docker containers:
- One that prints a message and exits.
- One that runs a full web server and keeps going in the background.
You didn’t install or configure anything manually.
Docker pulled the container image, started it, and wired up everything behind the scenes — all from one command.
This is the power of Docker: fast, isolated, repeatable environments that just work.
Now that you’ve seen it in action, let’s lift the curtain and walk through what actually happened behind the scenes when you ran that command.
👉 Next: How Docker Works Behind the Scenes
How Docker Works Behind the Scenes
So far, you’ve installed Docker, run your first container, and even spun up a real web server with a single line. Now let’s slow down and lift the hood. What actually happened when you ran those commands? Who did what? And how did it all just work?
In this section, we’ll walk through how Docker works behind the scenes using a simple mental model. This isn’t about low-level internals — it’s about helping you clearly understand how Docker’s parts talk to each other when you use it in day-to-day development.
The Big Picture
When you run a Docker command, you’re not talking to some mysterious black box. You’re interacting with a well-defined system made of three key components:
1. Docker Client (a.k.a. the CLI)
This is what you use in the terminal. Every time you type a command like:
|
|
…you’re using the Docker CLI, which is part of the Docker Client.
But the client doesn’t do the heavy lifting. It acts like a messenger. It takes your command and sends it as an API request to the Docker daemon, which is where the real action happens.
2. Docker Daemon (the engine that does the work)
The Docker Daemon is a background process that listens for requests and then does the real work. When you run a command, the daemon is the one that:
- Pulls container images (like
hello-world
ornginx
) - Builds images (we’ll do this in the next article)
- Starts and stops containers
- Manages networking and volumes
- And more
It’s the engine room of Docker.
You’ve been using it this whole time — indirectly. It was the daemon that made docker run nginx
actually spin up a running container.
And here’s something powerful: the daemon doesn’t have to run on your machine. In a CI/CD pipeline or in the cloud (like with Azure Container Instances), the Docker daemon might live on a remote VM or hosted container service. The architecture stays the same — only the location changes.
3. Docker Registry (where images come from)
When the daemon needs to create a container, it starts with an image. If that image (like nginx
) doesn’t already exist on your machine, it fetches it from a Docker registry.
By default, that’s Docker Hub. But it can also be a private registry — like Azure Container Registry.
Want to see those images for yourself?
- 🔍
hello-world
- 🔍
nginx
Each of those commands you’ve already run — they pulled one of these public images and used it to create a container.
What Actually Happened When You Ran docker run nginx
Let’s walk through what really happened when you ran that one-liner:
-
You typed:
1
docker run -d -p 8080:80 nginx
-
The Docker Client (CLI) turned that command into a request to the Docker Daemon.
-
The Docker Daemon checked if the
nginx
image already existed on your machine. If not, it pulled it from Docker Hub. -
The daemon used the image to create a container.
-
That container was started in detached mode, listening on port 80 inside the container, and exposed to your machine on port 8080.
-
You opened your browser and saw a working web server — powered by a container, running in seconds.
Let’s Visualise It
Here’s how the system fits together — from the moment you type a command to the moment a container starts:
In the diagram above:
- On the left, you (the developer) use the CLI to send commands.
- In the middle, the Docker Daemon runs locally (or remotely) and handles everything.
- On the right, the Registry is where the daemon pulls container images from.
Each part plays a clear role. Together, they make Docker feel seamless.
Why This Matters
Understanding this architecture gives you more than just vocabulary — it gives you confidence.
- You now know what happens under the hood.
- You understand which parts run locally and which can run remotely.
- You’re better equipped to troubleshoot, architect, and explain Docker to others.
This is the foundation for everything that comes next — not just running containers, but managing them.
You’ve already created and run real containers. But what happens after that?
How long do containers live? Where are they stored? How do you stop or remove them?
Next, we’ll explore exactly that:
the Docker container lifecycle — how to inspect, stop, clean up, and stay in control of the containers running on your system.
Let’s dive in.
The Docker Container Lifecycle
You’ve seen Docker run your first containers — one that exited (hello-world) and one that stayed running until you stopped it (nginx).
But what happened to those containers after the command ended?
Did they vanish? Are they still running? Can you bring them back?
In this section, you’ll learn how Docker containers live, pause, stop, and eventually get cleaned up — and how to manage them step-by-step.
A Visual Overview
Let’s start with the big picture.
This diagram shows the different states a container can move through:
- Created: The container has been created from an image, but hasn’t started yet.
- Running: The container is up and running.
- Paused: The container is running, but its processes are frozen.
- Stopped: The container has exited or been stopped.
- Removed: The container is completely deleted from your system.
And yes — every transition between these states is triggered by a specific command. Let’s walk through them as if you’re managing your own containers (because you are).
Listing Your Containers
Let’s first see what’s currently running on your system:
|
|
If you run this right now, you’ll likely see nothing. Why?
Because:
- The
hello-world
container exited immediately after printing its message. - The
nginx
container was stopped earlier, as we asked you to do.
So now try:
|
|
This shows all containers, including ones that have stopped.
You should see something like:
|
|
This output tells us:
- You ran
hello-world
and it exited. - You ran
nginx
, stopped it, and now it’s also in an “Exited” state.
These containers are still on your system, even if they’re not active.
Stopping a Running Container
If you had an active container (like nginx still running), you could stop it with:
|
|
For example:
|
|
Or even better, use the container’s name if you prefer:
|
|
You can find both the ID and the name using
docker ps -a
.
Starting or Restarting a Container
Want to start nginx again?
|
|
Or to restart it cleanly:
|
|
Now run:
|
|
You’ll see the nginx container is back in the Running state.
Pausing and Unpausing
Sometimes, you might want to temporarily freeze a container’s processes:
|
|
And then unpause it when you’re ready:
|
|
This is useful for quick troubleshooting or for controlling resource usage.
Removing Containers
If you’re done with a container and want to remove it entirely:
|
|
This deletes the container — but not the image it was created from.
If you want to remove multiple containers at once:
|
|
This deletes all stopped containers. It won’t touch running ones.
Optional: System Cleanup
Want to see how much space Docker is using?
|
|
To remove all unused containers, images, and volumes:
|
|
⚠️ Be careful with
system prune
. It will remove a lot — only use it when you’re sure you no longer need the stopped containers or dangling images.
Lifecycle Summary
- You run a container → it’s created and moves into Running.
- You can pause, stop, restart, or remove it.
- Even stopped containers stay on your system unless you remove them.
- Docker is designed to make these lifecycle transitions easy and fast.
Understanding this lifecycle is the key to managing your containers — keeping your system tidy, your containers under control, and your workflow smooth.
Before we wrap up, let’s quickly look at a few common issues you might run into, and how to fix them.
Common Issues and Troubleshooting
Docker is generally smooth once it’s up and running, but here are a few common hiccups you might run into — and how to fix them quickly.
1. Docker daemon not running
What you’ll see:
An error like:
Cannot connect to the Docker daemon. Is the docker daemon running?
What’s happening:
This usually means Docker isn’t running yet.
Fix:
Make sure Docker Desktop is started (on Windows/Mac). On Linux, check that the docker
service is running.
💡 Tip: If you’re unsure, just restart Docker Desktop — it solves most early issues!
2. Permission denied errors
What you’ll see (on Linux):
Something like:
Got permission denied while trying to connect to the Docker daemon
What’s happening:
Your user isn’t part of the docker
group, so Docker thinks you’re not authorised.
Fix:
Either prefix commands with sudo
, or add your user to the docker group.
3. Container won’t start
What you’ll see:
A container fails to start or exits immediately.
What’s happening:
This could be a config issue or something inside the app itself.
Fix:
Run docker logs <container_id>
to see what happened inside the container. The logs are your best friend here.
4. Docker taking up too much space
What’s happening:
After lots of containers and images, Docker can start hogging disk space.
Fix:
Run:
|
|
⚠️
system prune
will delete unused stuff — so use it when you’re sure you don’t need those old containers/images.
Key Takeaways
You’ve just completed your first real journey into Docker. Here’s what you now know how to do:
- 🔧 Install Docker and get it running on your machine
- 📦 Pull and run containers from public registries
- 🔁 Understand what happens behind the scenes — from CLI to daemon to registry
- 🧭 Manage the lifecycle of containers (start, stop, remove, clean up)
- 💡 Troubleshoot basic issues when something doesn’t work
That’s not just theory — that’s a full foundation for working with Docker day to day.
What’s Next?
You’ve been running containers. Now, it’s time to build your own.
In the next article, we’ll show you how to create your own Docker image using a Dockerfile
, push it to a cloud registry like Azure Container Registry, and run it in Azure Container Instances.
You’ll go from using containers to owning the whole container workflow — development to cloud.