Inspect Docker Swarm Secrets Without Exposing Their Contents
You will use docker secret inspect to read metadata for one or more Docker Swarm secrets, select a useful field with a Go template, and recognise the errors that mean you are on the wrong node or using the wrong name. The command is read-only, but its output can still reveal operational details. Allow about ten minutes if you already have access to a Swarm manager.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes Docker CLI 29.8.1, provided here by docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble. The command's contract is stable enough to be useful elsewhere, but exact fields and formatting should be checked with the installed help on older or newer releases.
1. Check the installed command
Start with read-only checks. Neither command changes Docker state, and neither normally needs sudo:
$ command -v docker
/usr/bin/docker
$ docker --version
Docker version 29.8.1, build 4a63305
$ docker secret inspect --help
Usage: docker secret inspect [OPTIONS] SECRET [SECRET...]
Display detailed information on one or more secrets
The syntax is docker secret inspect [OPTIONS] SECRET [SECRET...]. A secret can be identified by its name or ID. The command belongs to Docker Swarm, not to ordinary standalone-container administration, so the next check matters before you spend time debugging a secret name.
2. Confirm that the client reaches a Swarm manager
Inspecting a Swarm secret is a cluster-management operation. Run:
$ docker info --format '{{.Swarm.LocalNodeState}} {{.Swarm.ControlAvailable}}'
active true
Expect active true on a manager. The exact line may differ if your Docker version or context reports the values differently, so the useful facts are that Swarm is active and this node has manager control. If Docker says that the node is not a Swarm manager, switch to the correct Docker context or manager host. Do not initialise a new Swarm merely to make this inspection command run: that changes cluster state and is outside this guide.
Checkpoint: confirm the target context before inspecting anything sensitive:
$ docker context show
default
$ docker info --format 'server={{.ServerVersion}} swarm={{.Swarm.LocalNodeState}} manager={{.Swarm.ControlAvailable}}'
server=29.8.1 swarm=active manager=true
Your context name and server version will be different on many systems. If the context points at a production manager, treat every returned name, label and timestamp as production information.
3. Inspect one secret by name or ID
Use a real secret name from your approved inventory. The list command is also read-only:
$ docker secret ls
ID NAME DRIVER CREATED UPDATED
eo7jnzguqgtpdah3cm5srfb97 app-config <none> 3 minutes ago 3 minutes ago
$ SECRET_NAME='app-config'
$ docker secret inspect "$SECRET_NAME"
[
{
"ID": "eo7jnzguqgtpdah3cm5srfb97",
"Version": { "Index": 17 },
"CreatedAt": "2017-03-24T08:15:09.735271783Z",
"UpdatedAt": "2017-03-24T08:15:09.735271783Z",
"Spec": {
"Name": "app-config",
"Labels": { "env": "dev" }
}
}
]
The displayed timestamps, ID and version are examples of the shape, not values to expect on your host. By default the CLI renders results as a JSON array, even when you inspect one object. Secret inspection returns metadata such as identity, version, timestamps, name and labels. It does not provide a command for reading the secret payload. Do not try to substitute a host file path or a container environment variable for the secret name.
4. Select one field for scripts
Use --format or -f when a script needs one value rather than a complete JSON document. Docker executes the supplied Go template for each matching result:
$ docker secret inspect --format '{{.Spec.Name}}' "$SECRET_NAME"
app-config
$ docker secret inspect --format '{{.CreatedAt}}' "$SECRET_NAME"
2017-03-24 08:15:09.735271783 +0000 UTC
The timestamp above is illustrative. Your output will contain the value stored on the manager. Keep the template quoted so the shell passes the braces and spaces to Docker unchanged. If you need several fields, emit a deliberately simple, machine-readable line and handle escaping in the consuming program; do not parse the default human-facing JSON with a chain of fragile text filters.
The special format value json asks Docker to print JSON for each result:
$ docker secret inspect --format json "$SECRET_NAME"
{"ID":"eo7jnzguqgtpdah3cm5srfb97","Version":{"Index":17},"CreatedAt":"2017-03-24T08:15:09.735271783Z","UpdatedAt":"2017-03-24T08:15:09.735271783Z","Spec":{"Name":"app-config","Labels":{"env":"dev"}}}
Use --pretty when a person needs a friendlier display during an incident. It is still metadata output, not secret-content retrieval, and it is less suitable for scripts.
5. Inspect several secrets carefully
Pass multiple names or IDs after the options:
$ docker secret inspect --format '{{.Spec.Name}} {{.UpdatedAt}}' app-config api-token
app-config 2017-03-24 08:15:09.735271783 +0000 UTC
api-token 2017-03-24 08:16:11.735271783 +0000 UTC
Each result is formatted separately. A missing name causes the command to fail, so do not treat partial output as proof that every requested secret was found. For an automated check, capture the exit status and validate the number of returned records against the number of requested identifiers. Avoid broad output capture in shared terminals and CI logs, because names and labels can disclose deployment structure even when the payload remains protected.
6. Diagnose the common failures
These checks do not change state:
$ docker secret inspect definitely-not-a-real-secret
Error response from daemon: secret definitely-not-a-real-secret not found
$ printf 'exit status: %s\n' "$?"
exit status: 1
The exact error wording varies by Docker release. A non-zero status means the requested inspection did not complete; check the spelling, the current context and whether the object exists in this Swarm. A secret from another cluster will not appear just because its name is familiar.
If the daemon reports that this node is not a Swarm manager, stop there and use an approved manager context. Do not run docker swarm init on a host that belongs to an existing environment. If access is denied, ask for the narrowly scoped manager permission needed to read metadata. Do not add yourself to a broad administrative group merely to inspect one secret. If the daemon is unreachable, fix the Docker context or service access first; changing the secret is not a connectivity test.
Done means
- The command and Docker CLI version were checked locally.
- The active context reaches a Swarm manager, or the manager-context blocker was recorded.
- The requested secret was identified by an approved name or ID.
- The default JSON, a selected field, or
--prettyoutput was chosen for the actual reader. - No secret payload was copied into a command, terminal transcript or log.
- The command's exit status was checked, especially when several secrets were requested.