Description
When using extends to pull in an external service definition, the expected behavior is to merge the volumes sequence with the key as the target path in the container. This design allows you to declare a named volume to be required in the source service, but then to customize the name of that volume in the destination service (the one with the extends key) as long as you target the same path.
It seems that docker compose is not doing this quite right where docker-compose is.
Steps to reproduce the issue:
- Suppose you have a stack file,
foo.yml:
# foo.yml
---
services:
my-app:
image: ubuntu
volumes:
- my-app-vol:/app
and a docker-compose.yml:
# docker-compose.yml
---
services:
app1:
extends:
file: foo.yml
service: my-app
volumes:
- app1-data:/app
volumes:
app1-data:
- Attempt to compile the config with
docker compose config and observe:
$ docker compose config
service "app1" refers to undefined volume my-app-vol: invalid compose project
- Note that
docker-compose config produces the expected compiled config with the single volume, merged from the two volumes sequences key'ing off of the target path:
$ docker-compose config
services:
app1:
image: ubuntu
volumes:
- app1-data:/app:rw
version: '3.9'
volumes:
app1-data: {}
Describe the results you received:
Using docker compose fails to properly merge the volumes sequence and complains about an invalid compose project.
Describe the results you expected:
Use of docker compose should be equivalent to docker-compose, which seems to produce the correct behavior.
Output of docker-compose --version:
docker-compose version 1.29.2, build 5becea4c
Output of docker version:
Client: Docker Engine - Community
Cloud integration: 1.0.17
Version: 20.10.7
API version: 1.41
Go version: go1.13.15
Git commit: f0df350
Built: Wed Jun 2 11:56:47 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.7
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: b0f5bc3
Built: Wed Jun 2 11:54:58 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.6
GitCommit: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc:
Version: 1.0.0-rc95
GitCommit: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Output of docker info:
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)
compose: Docker Compose (Docker Inc., v2.0.0-beta.6)
scan: Docker Scan (Docker Inc., v0.8.0)
Server:
Containers: 34
Running: 4
Paused: 0
Stopped: 30
Images: 82
Server Version: 20.10.7
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: active
NodeID: lbeujprm4qt955n8rv1dff6rc
Is Manager: true
ClusterID: z9wresmnlyehnlxmnnew1uzub
Managers: 1
Nodes: 1
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
Data Path Port: 4789
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 10
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 192.168.65.3
Manager Addresses:
192.168.65.3:2377
Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
Default Runtime: runc
Init Binary: docker-init
containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 5.4.72-microsoft-standard-WSL2
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 12
Total Memory: 24.91GiB
Name: docker-desktop
ID: NWF2:DOVN:QUXC:I3AH:2G2C:EN6M:VE44:IAB3:IZ3E:TMMY:VZJB:ZJRK
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
Additional environment details (AWS ECS, Azure ACI, local, etc.):
Docker Desktop 3.5.2 (66501) running in WSL2 engine.
Description
When using extends to pull in an external service definition, the expected behavior is to merge the
volumessequence with the key as the target path in the container. This design allows you to declare a named volume to be required in the source service, but then to customize the name of that volume in the destination service (the one with theextendskey) as long as you target the same path.It seems that
docker composeis not doing this quite right wheredocker-composeis.Steps to reproduce the issue:
foo.yml:and a
docker-compose.yml:docker compose configand observe:$ docker compose config service "app1" refers to undefined volume my-app-vol: invalid compose projectdocker-compose configproduces the expected compiled config with the single volume, merged from the two volumes sequences key'ing off of the target path:$ docker-compose config services: app1: image: ubuntu volumes: - app1-data:/app:rw version: '3.9' volumes: app1-data: {}Describe the results you received:
Using
docker composefails to properly merge thevolumessequence and complains about an invalid compose project.Describe the results you expected:
Use of
docker composeshould be equivalent todocker-compose, which seems to produce the correct behavior.Output of
docker-compose --version:Output of
docker version:Output of
docker info:Additional environment details (AWS ECS, Azure ACI, local, etc.):
Docker Desktop 3.5.2 (66501) running in WSL2 engine.