Secrets & configs in Swarm
Delivering sensitive data to services.
Swarm has first-class secret management, and it is markedly better than passing sensitive values as environment variables. A Docker secret is stored encrypted in the Raft log, delivered only to the nodes running a service that was granted it, and mounted into the container as an in-memory file under /run/secrets — never written to the node’s disk, never baked into the image, never visible in docker inspect. You create it once and grant it to services explicitly.
$ printf 'S3cr3tP@ss' | docker secret create db_password -$ docker secret lsID NAME CREATEDq7w8e9 db_password 10 seconds ago$ docker service create --name db \--secret db_password \-e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \postgres:16
How delivery works
The secret is mounted as a tmpfs (memory-backed) file at /run/secrets/<name>, only inside the containers granted it and only on the nodes where those tasks run. Because it is a file in RAM, it sidesteps the classic environment-variable leaks — it is not in the process environment, not in logs, not in inspect output — and it disappears when the task stops. Apps read the file; many images accept a _FILE-suffixed env var pointing at it.
$ docker exec $(docker ps -qf name=db) cat /run/secrets/db_passwordS3cr3tP@ss$ docker exec $(docker ps -qf name=db) sh -c 'mount | grep /run/secrets'tmpfs on /run/secrets/db_password type tmpfs (ro,relatime) # RAM, read-only
Scenario: rotate a secret with no downtime
A credential must change, and secrets are immutable by design — you cannot edit one in place. Rotate by creating the new version, then updating the service to remove the old secret and add the new in a single rolling update, so tasks pick up the new file as they are replaced. The immutability is a feature: every secret version is a distinct, auditable object.
$ printf 'N3wP@ss2' | docker secret create db_password_v2 -$ docker service update \--secret-rm db_password \--secret-add source=db_password_v2,target=db_password \db # rolling update swaps the file under the app$ docker secret rm db_password # once no service references the old one
Configs for non-secret files
For non-sensitive files a service needs — an nginx.conf, a settings file — Swarm has docker config, which works exactly like secrets (create once, mount into the service) but without the encryption emphasis, since the content is not sensitive. It is the clean way to ship configuration into services without baking it into the image or bind-mounting from individual nodes.
$ docker config create nginx_conf ./nginx.conf$ docker service create --name web \--config source=nginx_conf,target=/etc/nginx/nginx.conf \nginx:1.27# rotate configs the same immutable way: create v2, --config-rm + --config-add