Essential CLI Commands
Summary
- The everyday Docker workflow reduces to a handful of verbs:
build,run,exec,logs,inspect,push, andpull. - Insight: every command is a REST call to
dockerd, so the same commands work against local, remote, and rootless engines with no syntax change. - Key Concepts: image (immutable OCI artifact), container (a running instance), registry (image storage), and contexts for selecting which engine you target.
- When to Use: this is the reference for CI pipelines, debugging live containers, and promoting images to a registry.
- Limitations: the CLI manages single containers, not clusters. For multi-node orchestration, images move on to Kubernetes and containerd.
Recipe
The minimal build-to-run-to-ship loop is four commands.
docker build -t registry.example.com/api:1.4.0 .
docker run --rm -p 8080:8080 registry.example.com/api:1.4.0
docker login registry.example.com
docker push registry.example.com/api:1.4.0Build produces an image, run verifies it locally, and push promotes it to a registry your cluster can pull from.
Working Example
Here is a realistic sequence covering build, run, debug, and ship for a small service.
# 1. Build with BuildKit, tagging with an immutable version
docker build -t registry.example.com/api:1.4.0 .
# 2. Run detached with resource limits and a health-friendly port map
docker run -d --name api \
-p 8080:8080 \
--memory=512m --cpus=1 \
registry.example.com/api:1.4.0
# 3. Follow logs to confirm startup
docker logs -f api
# 4. Exec in to check config or run a migration
docker exec -it api sh -c 'env | grep DB_'
# 5. Inspect the container's IP, mounts, and state as JSON
docker inspect api --format '{{.State.Status}} {{.NetworkSettings.IPAddress}}'
# 6. Pull a dependency image explicitly (e.g. for an integration test)
docker pull postgres:17
# 7. Authenticate and push the release
docker login registry.example.com
docker push registry.example.com/api:1.4.0
# 8. Tear down cleanly
docker rm -f apiEvery step here is portable to CI because none of it depends on interactive state.
Deep Dive
docker build
build sends a context (the directory and its Dockerfile) to BuildKit, which resolves a dependency graph and caches layers.
Use --build-arg for build-time variables and --target to stop at a named stage in a multi-stage build.
For multi-arch images, docker buildx build --platform linux/amd64,linux/arm64 produces a manifest list in one pass.
Always tag with an immutable version. A moving latest makes rollbacks and cache reasoning unreliable.
docker run
run is create plus start. The flags you reach for most are -d (detached), -p (publish ports), -e (env vars), -v (mounts), and --rm (auto-remove).
Add --restart policies (no, on-failure, always, unless-stopped) for local resilience. In Kubernetes, the equivalent is the Pod restart policy and controller.
--memory and --cpus set cgroup limits, mirroring container resource limits you will later set in manifests.
docker exec
exec launches a new process inside a running container's namespaces. It is your live-debugging entry point.
Use -it for an interactive shell and -u to run as a specific user. Remember: changes here vanish when the container is recreated, since the image is immutable.
docker logs and docker inspect
logs replays whatever the container wrote to stdout/stderr, subject to the daemon's logging driver. --since, --until, and --tail bound the output.
inspect returns the full JSON state of any object. The --format flag with a Go template extracts exactly one field, which is invaluable in scripts.
docker pull and docker push
pull fetches image layers by digest from a registry; push uploads them. login stores credentials for private registries.
Pushing to a registry the cluster trusts is how images cross from your build host to containerd on nodes.
Gotchas
Forgetting --rm on throwaway runs leaves stopped containers accumulating. Periodically run docker container prune.
Publishing with -p 80:80 fails in rootless mode because low ports need privileges. Map a high host port instead.
docker logs shows nothing if the app logs to a file inside the container. Configure the app to log to stdout/stderr.
Relying on latest breaks reproducibility. Two docker pull myapp:latest calls a week apart can yield different images.
docker build . sends the whole directory as context. A missing .dockerignore can upload gigabytes and slow every build.
Alternatives
nerdctl is a Docker-compatible CLI that drives containerd directly, useful on nodes where Docker Engine is not installed.
podman offers the same command surface as a daemonless, rootless-first tool. Many docker commands work by aliasing podman.
crictl is the CRI debugging CLI for inspecting pods and containers on a Kubernetes node, where docker ps does not apply.
For builds specifically, buildx (bundled with Engine) unlocks multi-arch, remote, and cache-export features beyond the classic builder.
FAQs
Why does docker ps not show a container I just started? It probably exited. Run docker ps -a and check the logs for the crash.
How do I run a one-off command in a new container? docker run --rm image cmd creates a fresh container, runs the command, and removes it.
What is the difference between exec and run? run starts a new container; exec runs a command inside an existing one.
Can I use these commands against a remote engine? Yes. Set a Docker context or DOCKER_HOST and the commands are unchanged.
How do I see why a container was OOM-killed? docker inspect --format '{{.State.OOMKilled}}' name returns true if the kernel killed it for memory.
Should I use docker commands on Kubernetes nodes? No. Nodes run containerd; use crictl or nerdctl there instead.
Related
- How the Docker Engine Works
- Docker Engine Basics
- Docker Contexts
- Engine Configuration
- Docker Engine Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).