Home / Alt manpages / docker(1)

  • docker(1)
  • User command
  • linux

Use the Docker CLI Safely: Contexts, Containers and Cleanup

You will finish with a small, repeatable Docker CLI workflow: confirm which daemon you are addressing, run a disposable container, inspect its output, enter a running container when needed, and remove what you created. The examples match Docker 29.8.1 and the docker-ce-cli package installed here as 5:29.8.1-1~ubuntu.24.04~noble.

Allow about fifteen minutes. You need a shell, the Docker CLI, access to a Docker daemon, and an image that you are permitted to run. Most commands below are ordinary user commands. Access to the daemon socket can itself grant broad control over the host, so treat membership of the Docker group and access to a remote Docker endpoint as administrative privileges.

1. Confirm the CLI and its endpoint

Start with read-only checks. The top-level docker command is a client for a daemon, and its global options apply before the subcommand. Check the installed version and the active context:

$ docker --version
Docker version 29.8.1, build 4a63305
$ docker context ls
NAME        DESCRIPTION                               DOCKER ENDPOINT
default *   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock

The asterisk marks the selected context. Do not assume that docker is talking to the local machine: a context, DOCKER_HOST, or an explicit -H can select another endpoint. The CLI configuration directory defaults to ~/.docker; use --config DIRECTORY when a separate client configuration is required.

Checkpoint: ask the daemon for a compact health and version report:

$ docker info --format 'Server {{.ServerVersion}} / Containers {{.Containers}} / Images {{.Images}}'
Server 29.8.1 / Containers 49 / Images 30

Your counts will differ. If this fails with a socket or connection error, stop here. Changing the context or starting a service is a separate administrative task, and adding sudo blindly can hide the real endpoint and permission problem.

2. Check the image before creating anything

List local images and choose one you recognise. This is read-only:

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
alpine       3         9234e837854f   ...           ...

Use an exact image reference in examples and scripts, such as alpine:3, rather than relying on whatever happens to be tagged latest. If the image is absent, docker run may pull it from a registry. That is a network and supply-chain decision: check the registry, image name, tag and trust policy before allowing a pull. Do not run an image from an untrusted source merely because its name looks familiar.

To discover the syntax of a command on this installed CLI, ask for its help:

$ docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Create and run a new container from an image

3. Run a disposable container

Run a short command with --rm. It prints the container's output and removes the container after it exits:

$ docker run --rm --name cli-smoke-test alpine:3 sh -c 'printf "container-ok\n"'
container-ok

This creates a container, but the removal is automatic when the command finishes. The name is useful while the container exists and makes errors easier to read. The command inside the container is separate from the Docker CLI command: sh -c and everything after it are arguments for the image's process.

Do not add host networking, host filesystem mounts, extra capabilities or privileged mode to make a test convenient. Those options cross security boundaries. Start with the smallest container and permissions that answer the question.

Checkpoint: confirm that the disposable container did not remain:

$ docker ps -a --filter name=cli-smoke-test
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

4. Keep a container for inspection

For a longer-lived test, detach a harmless process and give it a specific name:

$ docker run -d --name cli-inspection alpine:3 sh -c 'printf "started\n"; sleep 300'
7d2b... 

The returned identifier is abbreviated here and is different on every run. Check its state and logs:

$ docker ps --filter name=cli-inspection
CONTAINER ID   IMAGE      COMMAND                  STATUS         NAMES
7d2b...        alpine:3   "sh -c 'printf ...'"   Up ...         cli-inspection
$ docker logs cli-inspection
started

docker ps shows running containers. Add -a to include stopped containers. Logs are the process output captured by the container's logging setup, not a shell history or a full application audit trail.

5. Execute a command without confusing it with a new container

Use docker exec only against a running container. It starts an additional process in that container; it does not create a second container:

$ docker exec cli-inspection sh -c 'printf "exec-ok\n"'
exec-ok

For an interactive shell, allocate a terminal and keep standard input open:

$ docker exec -it cli-inspection sh
/ # id
uid=0(root) gid=0(root) groups=0(root)
/ # exit

The root user inside a container is not automatically harmless. It may have access to mounted data or capabilities granted at creation. Treat an interactive shell as a debugging tool, not as a reason to edit production state manually. Prefer a reproducible image or deployment change when the fix must survive recreation.

6. Stop and remove what you created

Stopping is the reversible first action. It asks the container's main process to exit:

$ docker stop cli-inspection
cli-inspection
$ docker ps --filter name=cli-inspection
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

The stopped container still exists and can be inspected with docker ps -a. When you are certain that its filesystem changes, logs and metadata are no longer needed, remove it:

$ docker rm cli-inspection
cli-inspection
$ docker ps -a --filter name=cli-inspection
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

Removal is destructive for the container's writable layer. It does not remove the image. Do not use docker rm -f casually: the -f option force-removes a running container and uses SIGKILL. If you attached anonymous volumes, review the command's volume options before adding -v, because that can remove data in those volumes. Named volumes and host bind mounts have their own lifecycle and need a separate review.

7. Diagnose the common failure paths

A missing image, a stopped container, a wrong context and a failed process are different problems. Use the object-specific checks rather than repeating the same command with more privilege:

  • Cannot connect to the Docker daemon: check docker context ls, the endpoint, and whether the daemon is available.
  • pull access denied or an unexpected pull: verify the image reference and registry, then check credentials with the approved authentication process.
  • No such container: list all containers with docker ps -a; names and context are local to the daemon you selected.
  • A non-zero application result: inspect docker logs CONTAINER and docker inspect CONTAINER; do not infer success from the container having been created.

For remote endpoints, TLS settings matter. The top-level CLI supports --tls, --tlscacert, --tlscert, --tlskey and --tlsverify. Use the certificates and endpoint supplied by the administrator. Never disable verification to get a connection working.

Done means

  • You confirmed the Docker CLI version and selected context.
  • You verified the daemon before creating a container.
  • You used a known image and a disposable --rm smoke test.
  • You can distinguish run, exec, ps, logs, stop and rm.
  • You stopped before destructive cleanup and understand what removal can delete.
  • You would investigate the endpoint, image, container state or application output before reaching for elevated privileges.