From lesson 1-2, docker run nginx starts a container, and the image is the frozen read-only package while the container is a live instance of it with its own writable layer.
Running a container never touches the image. That one-way relationship is what makes containers safe to throw away and images safe to share.
What docker run actually does
docker run is the docker command working engineers type most. It is how you get a Postgres for local development in one line, try a tool without installing it, or reproduce a bug in a clean environment. The classic first command:
docker run hello-world
Step by step, Docker:
- Looks for an image called
hello-worldon your machine - Doesn't find it, so it pulls (downloads) it from Docker Hub, the default public image registry
- Creates a new container from the image
- Starts the container, which prints a greeting
- The program ends, so the container exits
That last step matters: a container lives exactly as long as the one program it was started to run. When the program stops, the container stops. hello-world prints and quits, so its container is done in under a second.
Anatomy of the command
docker run -it python:3.12 pythonReading it piece by piece:
docker run: create and start a container-it: interactive mode with a terminal attached, so you can type into itpython:3.12: the image, asname:tag. The tag after the colon picks a version. Omit it and Docker assumes:latestpython(the last word): the command to run inside the container, overriding the image's default
That one line drops you into a real Python 3.12 prompt inside an isolated container, even if your laptop has no Python installed at all. Type exit() and the container stops.
Pin your tags. python:3.12 today is python:3.12 next year, but latest silently moves, which is the works-on-my-machine bug from lesson 1-1 sneaking back in.
Splitting an image reference in bash
Scripts parse image references constantly, and bash has built-in operators for it.
ref="python:3.12" echo "${ref%%:*}" echo "${ref##*:}"
Output
python
3.12| Expansion | Keeps |
|---|---|
${var%%:*} | everything before the first colon |
${var##*:} | everything after the last colon |
The %% form trims from the end and ## trims from the start, which is the opposite of what the symbols suggest on first reading. Doubling them means the longest possible match, so they work correctly even on a reference such as registry.io/team/app:v2 where more than one colon can appear.
A recorded session
This is a recorded Docker session, so you can read it without installing anything. It runs a first container and then looks at what the container left behind.
Step 1. Run the hello-world image. Docker will pull it first since this machine has never seen it.
you@laptop $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world Digest: sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly.
Step 2. List running containers. The hello-world container already exited, so expect an empty list.
you@laptop $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Step 3. Now list all containers, including stopped ones, with the -a flag.
you@laptop $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3f2a1c9be8d4 hello-world "/hello" 10 seconds ago Exited (0) 9 seconds ago jolly_wozniak
Step 4. The image is still on disk. List local images.
you@laptop $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest d2c94e258dcb 8 months ago 13.3kB
Naming the part after the colon
In python:3.12, the part after the colon is the tag.
Image references are name:tag, where the tag selects a specific version such as 3.12 or latest. It picks which version of the image you get, and omitting it makes Docker assume latest.
| Reference | Resolves to |
|---|---|
python:3.12 | that specific version |
python | python:latest |
Tags become central in unit 6 when images are pushed to a registry, and in lesson 8-3 they are the mechanism a rollback uses. Relying on latest in production is a known hazard, because the same reference means different bytes over time.