Home / Alt manpages / docker-secret(1)

  • docker-secret(1)
  • User command
  • linux

Create and Rotate Docker Swarm Secrets Safely

The day a database password needs to change is the day you discover Docker secrets cannot be edited, only replaced. This walks through creating a Swarm secret from standard input, confirming it exists without ever printing its value, and retiring it once nothing depends on it any more. About ten minutes on a running Swarm manager, using Docker CLI 29.8.1 from docker-ce-cli.

Secret commands are Swarm management commands: you need a running Swarm and a manager node, not just a Docker install. Run the examples as your normal account; add sudo only if your Docker socket policy specifically requires it.

1. Check the CLI and Swarm role

Start by checking the client and the local node state. This changes nothing:

$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker info --format '{{.Swarm.LocalNodeState}} {{.Swarm.ControlAvailable}}'
active true

You need active true. If the state is inactive, do not run docker swarm init on a host that belongs to someone else's deployment. Ask the Swarm administrator for a manager endpoint, or follow your site's cluster recovery process instead. A worker can run ordinary container commands, but it cannot create, list or remove Swarm secrets.

Checkpoint

Continue only when the client reaches an active manager. A local machine reporting an inactive Swarm cannot run any of the examples below without first changing cluster state.

2. Create a secret without putting the value in shell history

Pipe the value in and finish with a bare - to read standard input. The name must be unique within the Swarm. This creates a disposable test value:

$ printf '%s\n' 'REPLACE_WITH_A_TEST_VALUE' | docker secret create demo_api_key -
q1w2e3r4t5y6u7i8o9p0a1s2d

That output is an ID, not the secret, and it will differ every time you run this. Avoid writing a real credential directly on a command line: shell history, process inspection and copied terminal logs can all retain it. For a file-backed value, use docker secret create SECRET_NAME /path/to/file; check the file's permissions first, and remember the Docker client reads that path itself.

Creation changes cluster state. If the value is real, note where it is used and how it will be rotated before you create it: Docker has no in-place update for a secret.

3. Verify the name and metadata

List names and IDs with docker secret ls, which includes creation and update timestamps:

$ docker secret ls
ID                          NAME          CREATED             UPDATED
q1w2e3r4t5y6u7i8o9p0a1s2d   demo_api_key  10 seconds ago      10 seconds ago

Filter when the Swarm holds many secrets. Your timestamps and IDs will differ:

$ docker secret ls --filter name=demo_api_key
$ docker secret ls --quiet

ls is not a value check: Docker deliberately never prints secret contents. For metadata, inspect it instead:

$ docker secret inspect demo_api_key
[
    {
        "ID": "q1w2e3r4t5y6u7i8o9p0a1s2d",
        "Spec": {
            "Name": "demo_api_key"
        }
    }
]

The full JSON also carries timestamps and other metadata, never the payload. Treat it as operational data anyway: names and labels can still reveal system details.

4. Attach a secret to a service deliberately

A secret only earns its keep once a Swarm service grants a task access to it. That is a separate command, but the boundary matters: a secret is not an environment variable, and no container gets it automatically. When you create or update the service, select the secret explicitly with --secret or --secret-add. Docker mounts it inside the task, normally under /run/secrets/.

Inspect the service specification before you change it:

$ docker service inspect SERVICE_NAME --format '{{json .Spec.TaskTemplate.ContainerSpec.Secrets}}'

Replace SERVICE_NAME with the real service name. Never paste secret contents into service labels, environment variables, build arguments or logs: each of those has different exposure and a different lifetime.

Checkpoint

Before you rotate anything, identify every service using demo_api_key. The daemon rejects removal of a secret a running service still uses, but plan the change rather than leaning on that as your safety net.

5. Rotate by adding a new name

Because a secret cannot be updated, rotation means a new versioned name. Create the replacement from standard input:

$ printf '%s\n' 'REPLACE_WITH_THE_NEW_VALUE' | docker secret create demo_api_key_v2 -
z9x8c7v6b5n4m3a2s1d0f9g8h

Update the service to consume demo_api_key_v2, wait for the rollout, then test the application against the new credential. Keep the old secret in place until the service has converged and no task still needs it. The exact update command depends on your service image and its current secret target, so copy the live specification before you edit it.

Recovery

A failed update is recoverable. Leave the old secret attached, fix the service configuration, and retry the rollout. Do not remove the old secret first.

6. Remove a secret only after detaching it

Warning

docker secret rm is destructive and asks for no confirmation. It cannot be undone. Confirm first that no service still references the secret, then remove it by exact name or ID:

$ docker secret rm demo_api_key
demo_api_key

If a service still uses it, the daemon refuses and names that service. Detach it through the service update workflow, verify the replacement tasks are healthy, then retry. Do not stop production tasks or remove a service just to force this command through.

If you remove one by accident, Docker cannot hand the value back. Recreate it from the authoritative credential source under a new versioned name, update the affected service, and revoke the old credential upstream if that is warranted.

Done means

  • Confirmed an active Swarm manager and the installed Docker CLI version.
  • Created the secret from standard input without ever printing its value.
  • Verified its name and ID with docker secret ls and its metadata with docker secret inspect.
  • Recorded which services use the secret before touching access.
  • Rotated by creating a new version, updating and testing the service, then removing the old secret.
  • Understand that docker secret rm is immediate, irreversible and deliberately non-interactive.