Find the Docker Containers That Matter with docker container ls

docker container ls finds the running or stopped containers you actually mean, then formats them for scripts too. You will finish with a small set of commands for narrowing the result safely and producing output scripts can consume. The examples use Docker CE CLI 29.8.1, installed here as package version 5:29.8.1-1~ubuntu.24.04~noble.

Allow about ten minutes. You need a shell and access to a Docker daemon. Listing is normally an ordinary operation, but access to the daemon socket is privileged on many Linux systems. These commands inspect state only: they do not create, stop, restart or remove containers.

1. Check the client and list running containers

Confirm which client is first in your path, then run the command without options:

$ docker --version
Docker version 29.8.1, build 4a63305
$ docker container ls
CONTAINER ID   IMAGE          COMMAND       CREATED        STATUS        PORTS       NAMES
a1b2c3d4e5f6   web:latest     "webd"        18 hours ago   Up 18 hours    127.0.0.1:29630->8080/tcp   web

Your rows will differ. The default is the first trap: docker container ls shows only containers that are running. A stopped container is not missing; it is outside this default view. docker container list and docker ps are aliases for the same operation, but the longer form makes the object being listed clear.

Checkpoint: if the command reports that it cannot connect to the daemon, check the daemon address and your permission to use the Docker socket. Do not immediately add sudo to scripts. Decide whether your local Docker access policy permits it, and keep the same client configuration when you test again.

2. Include stopped containers when investigating a service

Add --all, or its short form -a, when the question is about every container, not only current processes:

$ docker container ls --all
CONTAINER ID   IMAGE          COMMAND       CREATED        STATUS                     PORTS       NAMES
a1b2c3d4e5f6   web:latest     "webd"        18 hours ago   Up 18 hours                127.0.0.1:29630->8080/tcp   web
91e0f9c4c3aa   example:1.2    "/start"      2 days ago     Exited (1) 2 days ago                   example-old

Use this view after a failed deployment or an unexpected restart. The STATUS column includes useful detail such as an exit code, but it is formatted for people. For a precise exit-code search, filter with exited:

$ docker container ls --all --filter 'exited=1'
CONTAINER ID   IMAGE          COMMAND   CREATED      STATUS                     PORTS   NAMES
91e0f9c4c3aa   example:1.2    "/start"   2 days ago   Exited (1) 2 days ago            example-old

The exited filter is useful with --all. Without it, a container that has already stopped cannot appear in the default running-only result.

3. Filter by name, status or label

Filters use key=value. Pass --filter more than once when you need more than one condition:

$ docker container ls --all \
    --filter 'name=web' \
    --filter 'status=running'
CONTAINER ID   IMAGE          COMMAND   CREATED      STATUS        PORTS   NAMES
6b7f2a1e90d4   example:web   "/run"    3 hours ago   Up 3 hours             web-api

Name matching accepts part of a container name, so name=web can match more than one result. Review the output before using it in a follow-up command. Status values include created, running, paused, restarting, removing and exited; the current Docker documentation also lists dead.

Labels are a better boundary for automation because they express why a container belongs to a group:

$ docker container ls --all --filter 'label=com.example.owner=platform'
CONTAINER ID   IMAGE          COMMAND   CREATED      STATUS        PORTS   NAMES
6b7f2a1e90d4   example:web   "/run"    3 hours ago   Up 3 hours             web-api

Use label=KEY to match the presence of a label, or label=KEY=VALUE to require its value. Quote the complete filter so a shell cannot reinterpret characters in a value supplied by another person or system.

4. Find ports, volumes and networks

Use resource filters when you know what the container exposes or mounts:

$ docker container ls --all --filter 'publish=443/tcp'
$ docker container ls --all --filter 'volume=/data'
$ docker container ls --all --filter 'network=frontend'

publish finds published ports, while expose finds exposed ports. Include /tcp or /udp when protocol matters; TCP is the default when the protocol is omitted. A port range is written like 8000-8080/tcp. The volume filter accepts a volume name or a mount path, and network accepts a network name or ID.

These filters answer different questions. A published port is reachable through a host-side mapping, whereas an exposed port is metadata about the container. Do not treat an exposed port as proof that a service is reachable from outside the container.

5. Make output stable for a human or a script

Use --format when the default wide table contains more detail than you need. A Go template without the table directive has no header:

$ docker container ls --format '{{.ID}} {{.Names}} {{.Status}}'
a1b2c3d4e5f6 web Up 18 hours
9f8e7d6c5b4a webhooks.example.com Up 20 hours (healthy)

For a readable custom table, declare the columns explicitly and use \t between them:

$ docker container ls --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}'
CONTAINER ID   IMAGE          STATUS        NAMES
a1b2c3d4e5f6   web:latest     Up 18 hours   web

Useful placeholders include .ID, .Image, .Command, .CreatedAt, .RunningFor, .Ports, .State, .Status, .Names, .Labels, .Mounts and .Networks. Use .Label "KEY" when you need one label rather than the complete label string.

For machine-readable output, request JSON:

$ docker container ls --format json
{"Command":"\"/webd\"","ID":"a1b2c3d4e5f6","Image":"web:latest","Names":"web","State":"running","Status":"Up 18 hours"}

Do not parse the human table with awk and assume its spacing is an interface. Prefer a template or JSON, and treat fields such as status text as display data rather than a stable API contract.

6. Handle IDs, ordering and truncation deliberately

When another command needs container identifiers, --quiet prints only IDs:

$ docker container ls --all --filter 'status=exited' --quiet
91e0f9c4c3aa
2d6b0c2a6f11

This is safe as an inspection step, but be careful before piping IDs into a command that changes state. A pipeline such as docker container ls -aq | xargs docker rm can remove every stopped container, including one you still need for logs or evidence. It is intentionally not used here. Confirm exact names or IDs and check the command's manual before any stop, restart or removal operation.

Use --latest to show the newest created container, or --last N for the last N created containers. Both include all states. These options describe creation order, not start order, so they are not a substitute for a timestamped deployment record. Add --no-trunc when a full ID or complete command is needed, and --size when you need each container's writable-layer and virtual-size information. Size inspection can be slower on a busy host.

Done means