Repository: docker/compose-cli
Pull request #1032 (2020-12-08 16:51:18)

Compose anonymous volumes + fix container volume source
**What I did**
* update compose-go to allow anonymous volumes
* found out that containers were attached to wrong volume name, in case of compose volumes (not external). Side effect was new volume created by the engine when creating container, with the volume name minus prefix "project_". 

**Related issue**
Fixes https://github.com/docker/compose-cli/issues/1026

<!-- optional tests
You can add a / mention to run tests executed by default only on main branch : 
* `test-aci` to run ACI E2E tests
* `test-ecs` to run ECS E2E tests
* `test-windows` to run tests & E2E tests on windows
-->

**(not mandatory) A picture of a cute animal, if possible in relation with what you did**
![](https://thumbs.dreamstime.com/z/cartoon-octopus-holding-pencil-illustration-83149526.jpg)


Patch:
diff --git a/go.mod b/go.mod
index 0fd8961a..98870777 100644
--- a/go.mod
+++ b/go.mod
@@ -32,7 +32,7 @@ require (
 	github.com/aws/aws-sdk-go v1.35.33
 	github.com/awslabs/goformation/v4 v4.15.6
 	github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
-	github.com/compose-spec/compose-go v0.0.0-20201126191557-f67043ab8858
+	github.com/compose-spec/compose-go v0.0.0-20201208135325-bcfd1e07a97e
 	github.com/containerd/console v1.0.1
 	github.com/containerd/containerd v1.4.0-0
 	github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a // indirect
@@ -48,7 +48,7 @@ require (
 	github.com/gobwas/ws v1.0.4
 	github.com/golang/mock v1.4.4
 	github.com/golang/protobuf v1.4.3
-	github.com/google/go-cmp v0.5.3
+	github.com/google/go-cmp v0.5.4
 	github.com/gorilla/mux v1.7.4 // indirect
 	github.com/hashicorp/go-multierror v1.1.0
 	github.com/hashicorp/go-uuid v1.0.2
diff --git a/go.sum b/go.sum
index 0e21da6e..5452c674 100644
--- a/go.sum
+++ b/go.sum
@@ -156,8 +156,8 @@ github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e h1:Qux+lbuMaRzkQy
 github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
-github.com/compose-spec/compose-go v0.0.0-20201126191557-f67043ab8858 h1:WQwUE7mbwbCDuuVc53R9cROmEs7ilXjyFEtiRSZumxY=
-github.com/compose-spec/compose-go v0.0.0-20201126191557-f67043ab8858/go.mod h1:Pm8gjIoib7x9av1XGkijXddjyV4aTHEq9EwVOvWH624=
+github.com/compose-spec/compose-go v0.0.0-20201208135325-bcfd1e07a97e h1:sfRp4eLv+F9ml4Yh49DPkIlEj07N0p/56FzCLbbROJ0=
+github.com/compose-spec/compose-go v0.0.0-20201208135325-bcfd1e07a97e/go.mod h1:rz7rjxJGA/pWpLdBmDdqymGm2okEDYgBE7yx569xW+I=
 github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
 github.com/containerd/cgroups v0.0.0-20200217135630-d732e370d46d/go.mod h1:CStdkl05lBnJej94BPFoJ7vB8cELKXwViS+dgfW0/M8=
 github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
@@ -363,8 +363,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -541,8 +541,8 @@ github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
-github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
+github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
 github.com/moby/buildkit v0.7.0 h1:5T41l8i0f+OqHvRThh2NKVXiLpclXYmgO8QePoyIJrw=
 github.com/moby/buildkit v0.7.0/go.mod h1:zOhLO1TiQepuSfzoNDQ542IGJQy0CHr79T4MOJvaewY=
@@ -1076,6 +1076,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
diff --git a/local/compose/create.go b/local/compose/create.go
index 94bae858..2eafbf2b 100644
--- a/local/compose/create.go
+++ b/local/compose/create.go
@@ -144,7 +144,7 @@ func getContainerCreateOptions(p *types.Project, s types.ServiceConfig, number i
 		StopTimeout: convert.ToSeconds(s.StopGracePeriod),
 	}
 
-	mountOptions, err := buildContainerMountOptions(s, inherit)
+	mountOptions, err := buildContainerMountOptions(*p, s, inherit)
 	if err != nil {
 		return nil, nil, nil, err
 	}
@@ -191,7 +191,7 @@ func buildContainerBindingOptions(s types.ServiceConfig) nat.PortMap {
 	return bindings
 }
 
-func buildContainerMountOptions(s types.ServiceConfig, inherit *moby.Container) ([]mount.Mount, error) {
+func buildContainerMountOptions(p types.Project, s types.ServiceConfig, inherit *moby.Container) ([]mount.Mount, error) {
 	mounts := []mount.Mount{}
 	var inherited []string
 	if inherit != nil {
@@ -217,7 +217,7 @@ func buildContainerMountOptions(s types.ServiceConfig, inherit *moby.Container)
 		if contains(inherited, v.Target) {
 			continue
 		}
-		mount, err := buildMount(v)
+		mount, err := buildMount(p, v)
 		if err != nil {
 			return nil, err
 		}
@@ -226,9 +226,9 @@ func buildContainerMountOptions(s types.ServiceConfig, inherit *moby.Container)
 	return mounts, nil
 }
 
-func buildMount(volume types.ServiceVolumeConfig) (mount.Mount, error) {
+func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.Mount, error) {
 	source := volume.Source
-	if volume.Type == "bind" && !filepath.IsAbs(source) {
+	if volume.Type == types.VolumeTypeBind && !filepath.IsAbs(source) {
 		// volume source has already been prefixed with workdir if required, by compose-go project loader
 		var err error
 		source, err = filepath.Abs(source)
@@ -236,6 +236,12 @@ func buildMount(volume types.ServiceVolumeConfig) (mount.Mount, error) {
 			return mount.Mount{}, err
 		}
 	}
+	if volume.Type == types.VolumeTypeVolume {
+		pVolume, ok := project.Volumes[volume.Source]
+		if ok {
+			source = pVolume.Name
+		}
+	}
 
 	return mount.Mount{
 		Type:          mount.Type(volume.Type),


Test patch:
diff --git a/local/compose/compose_test.go b/local/compose/compose_test.go
index 94d8460b..6aa29555 100644
--- a/local/compose/compose_test.go
+++ b/local/compose/compose_test.go
@@ -110,13 +110,34 @@ func TestStacksMixedStatus(t *testing.T) {
 }
 
 func TestBuildBindMount(t *testing.T) {
+	project := composetypes.Project{}
 	volume := composetypes.ServiceVolumeConfig{
 		Type:   composetypes.VolumeTypeBind,
 		Source: "e2e/volume-test",
 		Target: "/data",
 	}
-	mount, err := buildMount(volume)
+	mount, err := buildMount(project, volume)
 	assert.NilError(t, err)
 	assert.Assert(t, filepath.IsAbs(mount.Source))
 	assert.Equal(t, mount.Type, mountTypes.TypeBind)
 }
+
+func TestBuildVolumeMount(t *testing.T) {
+	project := composetypes.Project{
+		Name: "myProject",
+		Volumes: composetypes.Volumes(map[string]composetypes.VolumeConfig{
+			"myVolume": {
+				Name: "myProject_myVolume",
+			},
+		}),
+	}
+	volume := composetypes.ServiceVolumeConfig{
+		Type:   composetypes.VolumeTypeVolume,
+		Source: "myVolume",
+		Target: "/data",
+	}
+	mount, err := buildMount(project, volume)
+	assert.NilError(t, err)
+	assert.Equal(t, mount.Source, "myProject_myVolume")
+	assert.Equal(t, mount.Type, mountTypes.TypeVolume)
+}
diff --git a/tests/compose-e2e/compose_test.go b/tests/compose-e2e/compose_test.go
index f9e5f4d4..a36a67e3 100644
--- a/tests/compose-e2e/compose_test.go
+++ b/tests/compose-e2e/compose_test.go
@@ -120,10 +120,20 @@ func TestLocalComposeVolume(t *testing.T) {
 		c.RunDockerOrExitError("rmi", "compose-e2e-volume_nginx")
 		c.RunDockerOrExitError("volume", "rm", projectName+"_staticVol")
 		c.RunDockerCmd("compose", "up", "-d", "--workdir", "volume-test", "--project-name", projectName)
+	})
 
+	t.Run("access bind mount data", func(t *testing.T) {
 		output := HTTPGetWithRetry(t, "http://localhost:8090", http.StatusOK, 2*time.Second, 20*time.Second)
 		assert.Assert(t, strings.Contains(output, "Hello from Nginx container"))
+	})
+
+	t.Run("check container volume specs", func(t *testing.T) {
+		res := c.RunDockerCmd("inspect", "compose-e2e-volume_nginx2_1", "--format", "{{ json .HostConfig.Mounts }}")
+		//nolint
+		res.Assert(t, icmd.Expected{Out: `[{"Type":"volume","Source":"compose-e2e-volume_staticVol","Target":"/usr/share/nginx/html","ReadOnly":true},{"Type":"volume","Target":"/usr/src/app/node_modules"}]`})
+	})
 
+	t.Run("cleanup volume project", func(t *testing.T) {
 		_ = c.RunDockerCmd("compose", "down", "--project-name", projectName)
 		_ = c.RunDockerCmd("volume", "rm", projectName+"_staticVol")
 	})
diff --git a/tests/compose-e2e/volume-test/docker-compose.yml b/tests/compose-e2e/volume-test/docker-compose.yml
index 2574ed0e..57ec42fd 100644
--- a/tests/compose-e2e/volume-test/docker-compose.yml
+++ b/tests/compose-e2e/volume-test/docker-compose.yml
@@ -9,7 +9,8 @@ services:
   nginx2:
     build: nginx-build
     volumes:
-      - staticVol:/usr/share/nginx/html
+      - staticVol:/usr/share/nginx/html:ro
+      - /usr/src/app/node_modules
     ports:
       - 9090:80