Chapter 2 of 16 · Visual guide

Images & containers

The whole lifecycle in five verbs: pull, run, ps, stop, rm. Know which object each one touches.

key idea / Docker itselfcontainer / good pathhost / watch outproblem / blockedneutral

The container lifecycle

A container moves through a few states, and a different command moves it between each.

Container lifecycleRegistry to image with pull, image to running container with run, running to exited with stop, exited to removed with rm.Registrynginx:1.27pullImageon your diskrunRunningdocker psstopExiteddocker ps -armRemovedgonermi removes the Image box. rm removes the container. They are different objects.
docker run does the first three arrows in one command.
What docker run does1 · Image local?pull it if notif not2 · Createnew container + layerthen3 · Startlaunch the process
Run is three commands in one: pull if missing, create, start.

Tags are labels, not versions

Without a tag, Docker assumes latest, which can change under you.

The latest tag driftsA tag is a movable label. On Monday latest points to one image; on Friday it points to a different one.MondayFridayapp:latestimage abc123app:latestimage def456Same command, same tag......different code. Surprise in production.Pin it: nginx:1.27 (or an @sha256 digest for byte-exact images)

Removing things

Containers and images are separate objects with separate remove commands.

Why rmi is blockedBoth a running and an exited container reference the image, so removing the image fails until the containers are removed.nginx:1.27imagewebrunningold-webexitedusesusesdocker rmi: refusedRemove every container that uses an image first, then remove the image.
CommandRemovesFails when
docker rma containerit is still running (use stop first)
docker rmian imageany container, even stopped, still uses it
docker ps -a(lists)shows stopped containers that still exist

Try it yourself

  1. Step 1 · Pull a pinned tag
    $ docker pull nginx:1.27
    1.27: Pulling from library/nginx
    Status: Downloaded newer image for nginx:1.27
  2. Step 2 · The image is local
    $ docker images nginx
    REPOSITORY   TAG    IMAGE ID       CREATED       SIZE
    nginx        1.27   1b8b7c4a0c1a   2 weeks ago   192MB
  3. Step 3 · Run creates and starts a container

    -d returns the terminal immediately. --name web is the name you will use next.

    $ docker run -d --name web nginx:1.27
    a91c0e2f4b10…
    $ docker ps
    CONTAINER ID   IMAGE        STATUS         NAMES
    a91c0e2f4b10   nginx:1.27   Up 3 seconds   web
  4. Step 4 · Stop hides it from docker ps
    $ docker stop web
    web
    $ docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    $ docker ps -a
    CONTAINER ID   IMAGE        STATUS                      NAMES
    a91c0e2f4b10   nginx:1.27   Exited (0) 2 seconds ago    web
  5. Step 5 · rm deletes the container, rmi deletes the image

    The second command fails while web still exists. Remove the container, then the image.

    $ docker rmi nginx:1.27
    Error: conflict: unable to delete nginx:1.27 (must be forced) - container a91c0e2f4b10 is using its referenced image
    $ docker rm web
    web
    $ docker rmi nginx:1.27
    Untagged: nginx:1.27
    Deleted: sha256:1b8b7c4a0c1a…

Recap

Quick check

Why does docker rmi nginx:1.27 fail even though docker ps is empty?
Show answer

A stopped container still references the image. docker ps -a lists it; remove it with docker rm, then the image.