Unclear "secrets" merging behavior in "docker stack"
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.1k
- Forks
- 2.2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 43
Description
Description
Toplevel secrets defined partially in multiple Docker stack files are merged with an unclear behavior. In this particular case the base file is supposed to only define external: true and the override file define the exact external name.
Reproduce
Have these two files:
docker-stack.yml
version: "3.8"
services:
app:
image: foo
secrets:
- FOO_BAR
secrets:
FOO_BAR:
external: true
docker-stack.prod.yml
version: "3.8"
secrets:
FOO_BAR:
name: app-prod-foo-bar
Run docker stack config with these two files:
$ pwd
/home/mbrodala/example
$ docker stack config -c docker-stack.yml -c docker-stack.prod.yml
version: "3.8"
services:
app:
image: foo
secrets:
- source: FOO_BAR
secrets:
FOO_BAR:
name: app-prod-foo-bar
file: /home/mbrodala/example
Expected behavior
The expected output:
version: "3.8"
services:
app:
image: foo
secrets:
- source: FOO_BAR
secrets:
FOO_BAR:
name: app-prod-foo-bar
external: true
Incidentally this is exactly what docker compose config produces:
name: example
services:
app:
image: foo
networks:
default: null
secrets:
- source: FOO_BAR
target: /run/secrets/FOO_BAR
networks:
default:
name: example_default
secrets:
FOO_BAR:
name: app-prod-foo-bar
external: true
docker version
Client: Docker Engine - Community
Version: 29.7.2
API version: 1.55
Go version: go1.26.5
Git commit: a7dcaa6
Built: Wed Aug 5 18:29:26 2026
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 29.7.2
API version: 1.55 (minimum version 1.24)
Go version: go1.26.5
Git commit: 6a43e3d
Built: Wed Aug 5 18:29:26 2026
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v2.3.3
GitCommit: aad11006b869517fcd3009450b6f82da282e1a9b
runc:
Version: 1.4.3
GitCommit: v1.4.3-0-gbb14dabe
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker info
Client: Docker Engine - Community
Version: 29.7.2
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.36.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v5.5.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
rollout: Rollout new Compose service version (Karol Musur)
Version: v0.9
Path: /home/mbrodala/.docker/cli-plugins/docker-rollout
Server:
Containers: 25
Running: 9
Paused: 0
Stopped: 16
Images: 160
Server Version: 29.7.2
Storage Driver: btrfs
Btrfs:
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
CDI spec directories:
/etc/cdi
/var/run/cdi
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: aad11006b869517fcd3009450b6f82da282e1a9b
runc version: v1.4.3-0-gbb14dabe
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.16.9+deb14-amd64
Operating System: Debian GNU/Linux forky/sid
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 30.79GiB
Name: yui
ID: 155711a7-d70b-45a8-a98a-f6144758837a
Docker Root Dir: /var/lib/docker
Debug Mode: false
Username: mbrodala
Experimental: false
Insecure Registries:
::1/128
127.0.0.0/8
Live Restore Enabled: false
Firewall Backend: iptables
EnableUserlandProxy: true
UserlandProxyPath: /usr/bin/docker-proxy
Additional Info
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the merge with docker-stack.yml and docker-stack.prod.yml, then run docker stack config -c docker-stack.yml -c docker-stack.prod.yml. Trace how docker stack config merges top-level secrets, and consider the behavior complete when the output preserves external: true alongside the override name instead of adding a file path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100