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
- OSUbuntu 26.04 LTS (resolute)
- Docker Engine29.7.2
- Shellbash
- Architectureamd64
- TimeAbout 14 min
- Reviewed20 August 2026
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.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| DOCKER01 | 192.168.0.21 | Ubuntu 26.04 LTS | Docker Host | 2 Core | 4 GB | 50 GB |
Before you start
- Docker Engine running, and you have run at least one container - see guide 5.
- A shell where
docker psworks without sudo, or prefix each command withsudo.
-
Get an image before you need it
docker runpulls 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.22Expected 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. -
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.8MBExpected 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.
-
Run something in the background and rename it
sleep 300gives a container that stays alive with no service in it - useful for practising commands without a web server involved.docker renamechanges the handle without recreating anything; liketag, 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 secondExpected resultA container ID, silence from rename, then the container listed under its new name.
Success condition
docker psshows the new name. The container was never restarted - uptime continues from when it was created. -
Run a command inside a running container
docker execstarts 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-insideExpected resultThe text echoed back from inside the container.
Success conditionYou see the file contents. Add
-itfor an interactive shell:docker exec -it cg-box2 sh. -
Copy files between host and container
docker cpmoves files either direction usingcontainer:pathon 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-insideExpected resultThe file contents printed from the host copy.
Success conditionThe host file exists and matches. Reverse the arguments to copy host to container.
-
Ask a container about itself
docker inspectreturns the full JSON record for an object. It is far too long to read raw, so--formatis 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.225945133ZExpected resultThe image name, the command the container runs, and its creation timestamp.
Success conditionYou get one line rather than several hundred of JSON. Drop
--formatto see everything available. -
Clean up what you made
Removing a tag with
docker rmionly untags when other tags point at the same image - the underlying layers stay until the last reference goes. Note the output saysUntagged:and notDeleted:, 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-box2Expected result
Untagged:for the tag, and the container name echoed for the removal.Success condition
docker ps -aanddocker imagesno longer list them. Because alpine:3.22 still exists, no layers were deleted.
Troubleshooting
docker tag or docker rename printed nothing and you are unsure it worked
Why: Both succeed silently by design. Unix convention is that success is quiet.
Fix:Verify with a listing command rather than expecting a confirmation. Check the exit code if you are scripting.
bash docker tag alpine:3.22 cg-mine:v1; echo "exit=$?"exit=0Error: No such container - but you can see it in docker ps -a
Why: Most commands act on running containers only.
docker pshides stopped ones, andexeccannot attach to a container that is not running.Fix:Start it first, or use a command that works on stopped containers such as
docker cp,docker logsordocker inspect.bash docker ps -a --filter name=cg- --format "{{.Names}} {{.Status}}"docker start cg-box2 && docker exec cg-box2 echo now-running