Docker: images, containers and the daemon
Docker is the tool that made containers usable by everyone, and its commands are how you will build, run and manage containers day to day. Before writing your own image (the next lesson), you need to be comfortable with the moving parts — the daemon, images, containers, registries — and the everyday commands. This lesson is Docker's architecture and the commands you will actually use, tried against real images.
The pieces: daemon, client, images, registries
Docker has a few parts, and knowing them makes its behaviour make sense:
- The Docker daemon — a background service (
dockerd) that does the real work: building images, running containers, managing storage and networks. It runs on the host (on your laptop, Docker Desktop runs it). - The Docker client — the
dockercommand you type. It sends your commands to the daemon. Client and daemon are separate, which is why Docker can control a daemon on another machine too. - Images — the packaged bundles (the previous lesson). You build them or pull them.
- Containers — running instances of images.
- A registry — a store of images. Docker Hub is the public default; companies run private registries
(or use ones like Amazon ECR).
docker pulldownloads an image from a registry;docker pushuploads one.
So the flow is: the client tells the daemon to pull or build an image, then run it as a container; images come from and go to registries. Hold that and the commands slot into place.
Running your first container
The quickest way to see it work — run a public image:
docker run hello-world # pulls the image if needed, runs it, prints a message
docker run -it ubuntu bash # run Ubuntu interactively and get a shell inside it (exit to leave)
docker run -d -p 8080:80 nginx # run nginx in the background, mapping host port 8080 to container port 80
Break down that last, realistic one:
-d(detached) — run in the background and return your prompt (without it, the container holds your terminal).-p 8080:80— publish a port: map port 8080 on your host to port 80 inside the container, sohttp://localhost:8080reaches nginx. The format is alwayshost:container(the networking lesson's ports, made concrete).nginx— the image to run; Docker pulls it from Docker Hub if you do not have it.
docker run is the workhorse: it takes an image and starts a container from it, with flags controlling ports,
environment, background/foreground, and more.
Passing configuration and names
Real containers need configuration and are easier to manage with names:
docker run -d --name web -p 8080:80 nginx # give the container a name
docker run -e GREETING="Namaste" greetings:1.0 # set an environment variable with -e
docker run -d -p 3000:3000 --name greet greetings:1.0
-e KEY=value sets an environment variable inside the container — the standard way to configure a
containerised app (the "greetings" app reads GREETING and PORT from the environment exactly so it can be
configured this way without changing the image). --name gives the container a memorable handle instead of a
random one, so you can stop/logs/rm it by name.
Managing containers and images
The everyday management commands:
docker ps # running containers
docker ps -a # all containers, including stopped ones
docker images # images you have locally
docker logs web # the logs (stdout) of a container — your first debugging move
docker logs -f web # follow them live
docker exec -it web sh # run a command (here, a shell) INSIDE a running container
docker stop web # stop a running container (sends TERM, like the processes lesson)
docker rm web # remove a stopped container
docker rmi nginx # remove an image
Two you will use constantly: docker logs — when a container misbehaves, its logs are the first thing you
read (a containerised app should log to stdout so docker logs captures it); and
docker exec -it <name> sh — this drops you into a shell inside the running container, so you can look
around its filesystem,
check env vars, and debug from within. "The container is running but the app isn't working" is usually solved
by docker logs then docker exec to poke around inside.
Cleaning up
Containers and images accumulate and use disk (you saw this concept with deployment storage). Clean up periodically:
docker ps -a # see stopped containers taking up space
docker rm $(docker ps -aq) # remove all stopped containers (careful)
docker system df # how much disk Docker is using
docker system prune # remove stopped containers, unused networks and dangling images
docker system prune is the safe general cleanup; docker system df shows what is using space. Left
unmanaged, Docker will happily fill a disk with old images and stopped containers — a common cause of "the
build machine ran out of space".
Check your work
Pieces: the daemon (dockerd, does the work), the client (docker, sends commands), images
(bundles), containers (running images), and registries (image stores — Docker Hub default; pull/
push). Flow: client → daemon builds/pulls an image → runs it as a container; images live in registries.
docker run starts a container from an image: -d (background), -p host:container (publish a port),
-e KEY=value (env config), --name (a handle). Pulls the image if absent.
Manage: docker ps/ps -a (running/all), docker images, docker logs [-f] (a container's output —
first debug move), docker exec -it <name> sh (a shell inside a running container — debug from within),
docker stop/rm/rmi.
Clean up: docker system df (disk used), docker system prune (remove stopped containers/unused
networks/dangling images). Unmanaged Docker fills the disk.
Practice
- Run
docker run hello-worldanddocker run -it ubuntu bash; explore inside Ubuntu andexit. - Run nginx with
-d -p 8080:80, visithttp://localhost:8080, thendocker logsanddocker stopit. - Explain each part of
docker run -d --name greet -p 3000:3000 -e GREETING="Hi" greetings:1.0. - Use
docker exec -it <name> shto get a shell inside a running container and check an environment variable. - Use
docker ps -aanddocker imagesto see what exists, then remove a stopped container and an image. - Run
docker system dfanddocker system prune, and explain why cleanup matters on a build server.
Official documentation
- Docker — docker run reference — Every flag for running containers.
- Docker — CLI reference — The full command set.
- Docker — Docker overview / architecture — Daemon, client, images and registries.
Next: writing a good Dockerfile.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship