Edit config.json and you can make docker ps and docker images print columns you actually want. Every change here is reversible: back the file up first, and you can always put it back. Allow about 15 minutes for a first configuration and verification.
This guide is for the Docker command-line client on Linux. It was checked with Docker CLI 29.8.1 from docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble. You need a normal shell account and a working Docker client. The examples that list containers and images need access to a Docker daemon, but editing the client file itself does not need sudo.
Docker normally reads $HOME/.docker/config.json. The file is JSON, not a shell script. Docker manages other files in the .docker directory, so limit manual edits to config.json. If the file already exists, preserve its unrelated properties, especially credential-store settings.
Check the client version and the environment that can redirect the configuration directory:
$ docker --version
Docker version 29.8.1, build 4a63305
$ printf '%s\n' "${DOCKER_CONFIG:-$HOME/.docker}"
/home/USER/.docker
The second output is an example. Replace USER with your account name if you use the path in a later command. A set DOCKER_CONFIG changes the directory used by the client. The global --config option can select a different directory for one invocation, and takes precedence over DOCKER_CONFIG.
Checkpoint: Write down the directory printed by the command. If it is not the directory you expected, inspect your shell startup files before editing anything.
Make a dated copy only when the file exists:
$ config_dir="${DOCKER_CONFIG:-$HOME/.docker}"
$ config_file="$config_dir/config.json"
$ test -f "$config_file" && cp --preserve=mode,timestamps "$config_file" "$config_file.bak"
$ if test -f "$config_file.bak"; then printf 'backup: %s\n' "$config_file.bak"; else printf 'no existing config.json\n'; fi
backup: /home/USER/.docker/config.json.bak
If the backup command reports a permission error, stop and inspect ownership and permissions. Do not solve a client configuration problem by making the whole .docker directory world-readable. A Docker configuration can contain registry credentials, proxy URLs or references to a credential helper. Docker's documentation warns against sharing or committing it.
There is no need to restart Docker after changing this client file. The next Docker CLI invocation reads the selected configuration.
Use a JSON-aware editor if the file already contains settings. The smallest valid new file for this example is:
{
"psFormat": "table {{.Names}}\\t{{.Status}}"
}
psFormat is used when docker ps has no --format option. The table directive keeps column headings, and the JSON string needs two backslashes so that Docker receives the template's \t tab escape. Do not replace an existing configuration wholesale unless you have copied every setting you need.
Validate the result with an ordinary, read-only command:
$ docker ps --no-trunc | head -5
NAMES STATUS
parish Up 5 hours (healthy)
app Up 17 hours
web.example.com Up 19 hours (healthy)
Your rows will differ. The useful check is that the headings and columns match the template. An explicit format overrides the file:
$ docker ps --format 'table {{.ID}}\t{{.Image}}'
CONTAINER ID IMAGE
Checkpoint: If the explicit command works but the default does not, the client is probably reading another configuration directory. Re-run step 1 and check for a command alias or wrapper.
The separate imagesFormat property controls docker images and docker image ls when neither command supplies --format. Add it beside psFormat:
{
"psFormat": "table {{.Names}}\\t{{.Status}}",
"imagesFormat": "table {{.Repository}}\\t{{.Tag}}"
}
Verify both the legacy and object-style command:
$ docker images | head -5
REPOSITORY TAG
parish latest
app latest
app v0.3.0
$ docker image ls --format 'table {{.Repository}}\t{{.Tag}}' | head -3
REPOSITORY TAG
parish latest
Do not assume that a format property changes every Docker listing. Current Docker releases expose additional properties for other commands, but each command's documentation defines its own template fields. If a template is rejected or renders blank values, remove the new property, restore the backup, and test a simpler field.
The default sequence for an attached container is ctrl-p,ctrl-q. It leaves the container running while detaching your terminal. A configuration property such as "detachKeys": "ctrl-e,e" changes the client default for docker attach, docker exec, docker run and docker start when those commands do not receive their own --detach-keys option.
Add it only if the normal sequence conflicts with your terminal or application:
{
"psFormat": "table {{.Names}}\\t{{.Status}}",
"imagesFormat": "table {{.Repository}}\\t{{.Tag}}",
"detachKeys": "ctrl-e,e"
}
Test a per-command override before relying on the global setting. The command below starts a short-lived container and chooses a sequence for that invocation:
$ docker run --rm --detach-keys='ctrl-x,x' alpine:latest true
This example may pull an image if it is not already available. It does not keep a container running because true exits immediately. Treat detach sequences as a usability setting, not a security control. If you lose track of an attached terminal, use a second shell to inspect docker ps before sending signals or removing anything.
HttpHeaders adds named headers to messages sent by the Docker client to the daemon. Docker passes these headers through; it does not interpret them or let them replace headers it sets itself. Use this only for a documented integration that requires a harmless, non-secret value:
{
"HttpHeaders": {
"X-Client-Environment": "staging"
}
}
Do not put passwords, access tokens or private keys in this object. Headers can reach a remote daemon or an intermediary, and the configuration may be copied into backups. Current Docker releases also support the experimental DOCKER_CUSTOM_HEADERS environment variable, but the same exposure risk applies. Environment variables override properties in config.json, and command-line options override environment variables, so inspect all three layers when a value appears to be ignored.
For a new format, test without touching your real credentials or defaults. Put a minimal config.json in a temporary directory, then point one command at it:
$ mkdir -p /tmp/docker-config-test
$ editor /tmp/docker-config-test/config.json
$ docker --config /tmp/docker-config-test ps | head -3
NAMES STATUS
parish Up 5 hours (healthy)
The --config option applies to that command only. Do not copy your real configuration into /tmp, because temporary files may be readable by other local users depending on the directory permissions. Remove the test directory after checking it:
$ rm -rf /tmp/docker-config-test
This deletion is safe only for the disposable directory created above. Never substitute your real $HOME/.docker path.
If Docker reports invalid JSON or a command starts using unwanted defaults, stop using the broken file and restore the backup:
$ cp --preserve=mode,timestamps "$config_file.bak" "$config_file"
$ docker ps --format 'table {{.Names}}\t{{.Status}}' | head -3
NAMES STATUS
If the backup is unavailable, move the current file aside instead of deleting it, then create a minimal configuration with only settings you have verified. Removing a credential-store entry can change where future logins are saved, so check the file contents before any replacement. You do not need elevated privileges for these steps unless the file genuinely belongs to another account, in which case the correct fix is to use that account's Docker configuration.
config.json.psFormat or imagesFormat produces the expected columns, and an explicit --format still wins.detachKeys only for a deliberate terminal conflict.HttpHeaders, a temporary directory or version control.