CertGrid CertGrid
Hands-on Lab·Docker

Essential Docker CLI Commands

The dozen commands that cover most day-to-day container work, grouped by what you are trying to do rather than alphabetically. Each is run against a real host so you can see the exact output, including the commands that print nothing on success.

Containers and Images Guide 6 of 46 Beginner

Tested on the versions above. Container IDs, image IDs, digests and timestamps differ on every host. Match the shape of the output, not the exact strings.

One Docker host is all this guide needs. Nothing here depends on a second machine, and the hardware above is modest on purpose - a 2 core, 4 GB VM runs everything in this path.
Server NameIP AddressOSRolesCPURAMHDD
DOCKER01192.168.0.21Ubuntu 26.04 LTSDocker Host2 Core4 GB50 GB

Before you start

  1. Get an image before you need it

    docker run pulls automatically when an image is missing, but pulling explicitly is useful when you want the download to happen now rather than in the middle of a demo. A pull of an image you already have is cheap and reports that nothing changed.

    bash Example session
    docker pull alpine:3.223.22: Pulling from library/alpineDigest: sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dceStatus: Downloaded newer image for alpine:3.22docker.io/library/alpine:3.22

    Expected resultA digest line and the fully qualified image name.

    Success conditionThe final line is the canonical name. A repeat pull prints Status: Image is up to date.

  2. Give an image a second name with a tag

    Tagging does not copy anything. It adds another label pointing at the same image ID, which is why the tagged image reports the same ID as its source and costs no extra disk. This command prints nothing at all on success - silence is the success condition, which is worth knowing before you go looking for a confirmation message.

    bash Example session
    docker tag alpine:3.22 cg-mine:v1docker images --filter reference=cg-mine --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Size}}"REPOSITORY:TAG   IMAGE ID       SIZEcg-mine:v1       14358309a308   12.8MB

    Expected resultNo output from docker tag, then one row from the filtered image list.

    Success conditionThe new tag appears with the same image ID as the original. Nothing was duplicated on disk.

  3. Run something in the background and rename it

    sleep 300 gives a container that stays alive with no service in it - useful for practising commands without a web server involved. docker rename changes the handle without recreating anything; like tag, it succeeds silently.

    bash Example session
    docker run -d --name cg-box alpine sleep 300b6f3fc675e10f62aa7e499c8caf3f7b9e3450a9caeb2a91cd36a1c31cdd51e98docker rename cg-box cg-box2docker ps --filter name=cg- --format "{{.Names}} {{.Status}}"cg-box2 Up Less than a second

    Expected resultA container ID, silence from rename, then the container listed under its new name.

    Success conditiondocker ps shows the new name. The container was never restarted - uptime continues from when it was created.

  4. Run a command inside a running container

    docker exec starts an additional process inside an existing container. This is how you inspect a running system without restarting it. Remember that anything written this way lands in the container's writable layer and disappears when the container is removed - guide 12 covers making data survive.

    bash
    docker exec cg-box2 sh -c "echo written-inside > /tmp/f.txt; cat /tmp/f.txt"written-inside

    Expected resultThe text echoed back from inside the container.

    Success conditionYou see the file contents. Add -it for an interactive shell: docker exec -it cg-box2 sh.

  5. Copy files between host and container

    docker cp moves files either direction using container:path on one side. It works on stopped containers too, which makes it the usual way to retrieve a log or a core dump from something that has already crashed.

    bash
    docker cp cg-box2:/tmp/f.txt /tmp/cg-copied.txt && cat /tmp/cg-copied.txtwritten-inside

    Expected resultThe file contents printed from the host copy.

    Success conditionThe host file exists and matches. Reverse the arguments to copy host to container.

  6. Ask a container about itself

    docker inspect returns the full JSON record for an object. It is far too long to read raw, so --format is how it becomes useful - pull out only the fields you need. The same command works on images, networks and volumes.

    bash Example session
    docker inspect cg-box2 --format "image={{.Config.Image}} cmd={{.Config.Cmd}} created={{.Created}}"image=alpine cmd=[sleep 300] created=2026-08-20T05:46:40.225945133Z

    Expected resultThe image name, the command the container runs, and its creation timestamp.

    Success conditionYou get one line rather than several hundred of JSON. Drop --format to see everything available.

  7. Clean up what you made

    Removing a tag with docker rmi only untags when other tags point at the same image - the underlying layers stay until the last reference goes. Note the output says Untagged: and not Deleted:, which tells you the image itself is still there under its original name.

    bash
    # removal is permanent - check what you are naming before you run thesedocker rmi cg-mine:v1Untagged: cg-mine:v1docker rm -f cg-box2cg-box2

    Expected resultUntagged: for the tag, and the container name echoed for the removal.

    Success conditiondocker ps -a and docker images no longer list them. Because alpine:3.22 still exists, no layers were deleted.

Troubleshooting

Official sources