summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Goff <cpuguy83@gmail.com>2023-03-14 23:06:03 +0000
committerGitHub <noreply@github.com>2023-03-14 23:06:03 +0000
commit9740b6854d1737fab795e2c7f38b1115d8b53833 (patch)
treee98b439f11aae433b68ac564a31137441d5f67ab
parentf09528b7126f74b9a1ff82f1a55354d0c67b4574 (diff)
parentfd80ca60da47e1c4533c3a66679cf582e7acac66 (diff)
downloaddocker-9740b6854d1737fab795e2c7f38b1115d8b53833.tar.gz
Merge pull request #45159 from thaJeztah/23.0_backport_fix_volume_anon_from_image
[23.0 backport] Fix pruning anon volume created from image config
-rw-r--r--daemon/create_unix.go4
-rw-r--r--daemon/create_windows.go8
-rw-r--r--integration/internal/build/build.go52
-rw-r--r--integration/internal/container/container.go1
-rw-r--r--integration/volume/volume_test.go36
5 files changed, 91 insertions, 10 deletions
diff --git a/daemon/create_unix.go b/daemon/create_unix.go
index f6f9649eb5..118c427aac 100644
--- a/daemon/create_unix.go
+++ b/daemon/create_unix.go
@@ -13,7 +13,6 @@ import (
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/container"
"github.com/docker/docker/oci"
- "github.com/docker/docker/pkg/stringid"
volumeopts "github.com/docker/docker/volume/service/opts"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/sirupsen/logrus"
@@ -42,7 +41,6 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
}
for spec := range config.Volumes {
- name := stringid.GenerateRandomID()
destination := filepath.Clean(spec)
// Skip volumes for which we already have something mounted on that
@@ -62,7 +60,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
}
- v, err := daemon.volumes.Create(context.TODO(), name, hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
+ v, err := daemon.volumes.Create(context.TODO(), "", hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
if err != nil {
return err
}
diff --git a/daemon/create_windows.go b/daemon/create_windows.go
index f47b732fbd..c7220601f3 100644
--- a/daemon/create_windows.go
+++ b/daemon/create_windows.go
@@ -6,7 +6,6 @@ import (
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/container"
- "github.com/docker/docker/pkg/stringid"
volumemounts "github.com/docker/docker/volume/mounts"
volumeopts "github.com/docker/docker/volume/service/opts"
)
@@ -25,11 +24,6 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
return fmt.Errorf("Unrecognised volume spec: %v", err)
}
- // If the mountpoint doesn't have a name, generate one.
- if len(mp.Name) == 0 {
- mp.Name = stringid.GenerateRandomID()
- }
-
// Skip volumes for which we already have something mounted on that
// destination because of a --volume-from.
if container.IsDestinationMounted(mp.Destination) {
@@ -40,7 +34,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
// Create the volume in the volume driver. If it doesn't exist,
// a new one will be created.
- v, err := daemon.volumes.Create(context.TODO(), mp.Name, volumeDriver, volumeopts.WithCreateReference(container.ID))
+ v, err := daemon.volumes.Create(context.TODO(), "", volumeDriver, volumeopts.WithCreateReference(container.ID))
if err != nil {
return err
}
diff --git a/integration/internal/build/build.go b/integration/internal/build/build.go
new file mode 100644
index 0000000000..9dbdd1241e
--- /dev/null
+++ b/integration/internal/build/build.go
@@ -0,0 +1,52 @@
+package build
+
+import (
+ "context"
+ "encoding/json"
+ "io"
+ "testing"
+
+ "github.com/docker/docker/api/types"
+ "github.com/docker/docker/client"
+ "github.com/docker/docker/pkg/jsonmessage"
+ "github.com/docker/docker/testutil/fakecontext"
+ "gotest.tools/v3/assert"
+)
+
+// Do builds an image from the given context and returns the image ID.
+func Do(ctx context.Context, t *testing.T, client client.APIClient, buildCtx *fakecontext.Fake) string {
+ resp, err := client.ImageBuild(ctx, buildCtx.AsTarReader(t), types.ImageBuildOptions{})
+ if resp.Body != nil {
+ defer resp.Body.Close()
+ }
+ assert.NilError(t, err)
+ img := GetImageIDFromBody(t, resp.Body)
+ t.Cleanup(func() {
+ client.ImageRemove(ctx, img, types.ImageRemoveOptions{Force: true})
+ })
+ return img
+}
+
+// GetImageIDFRommBody reads the image ID from the build response body.
+func GetImageIDFromBody(t *testing.T, body io.Reader) string {
+ var (
+ jm jsonmessage.JSONMessage
+ br types.BuildResult
+ dec = json.NewDecoder(body)
+ )
+ for {
+ err := dec.Decode(&jm)
+ if err == io.EOF {
+ break
+ }
+ assert.NilError(t, err)
+ if jm.Aux == nil {
+ continue
+ }
+ assert.NilError(t, json.Unmarshal(*jm.Aux, &br))
+ assert.Assert(t, br.ID != "", "could not read image ID from build output")
+ break
+ }
+ io.Copy(io.Discard, body)
+ return br.ID
+}
diff --git a/integration/internal/container/container.go b/integration/internal/container/container.go
index dadc6b44e4..6559bd4f4a 100644
--- a/integration/internal/container/container.go
+++ b/integration/internal/container/container.go
@@ -48,6 +48,7 @@ func create(ctx context.Context, t *testing.T, client client.APIClient, ops ...f
// Create creates a container with the specified options, asserting that there was no error
func Create(ctx context.Context, t *testing.T, client client.APIClient, ops ...func(*TestContainerConfig)) string {
+ t.Helper()
c, err := create(ctx, t, client, ops...)
assert.NilError(t, err)
diff --git a/integration/volume/volume_test.go b/integration/volume/volume_test.go
index f9e1dfcb55..e3d0cd7b96 100644
--- a/integration/volume/volume_test.go
+++ b/integration/volume/volume_test.go
@@ -14,8 +14,10 @@ import (
"github.com/docker/docker/api/types/volume"
clientpkg "github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
+ "github.com/docker/docker/integration/internal/build"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/testutil/daemon"
+ "github.com/docker/docker/testutil/fakecontext"
"github.com/docker/docker/testutil/request"
"github.com/google/go-cmp/cmp/cmpopts"
"gotest.tools/v3/assert"
@@ -304,3 +306,37 @@ func TestVolumePruneAnonymous(t *testing.T) {
assert.Check(t, cmp.Contains(pruneReport.VolumesDeleted, v.Name))
assert.Check(t, cmp.Contains(pruneReport.VolumesDeleted, vNamed.Name))
}
+
+func TestVolumePruneAnonFromImage(t *testing.T) {
+ defer setupTest(t)()
+ client := testEnv.APIClient()
+
+ volDest := "/foo"
+ if testEnv.OSType == "windows" {
+ volDest = `c:\\foo`
+ }
+
+ dockerfile := `FROM busybox
+VOLUME ` + volDest
+
+ ctx := context.Background()
+ img := build.Do(ctx, t, client, fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)))
+
+ id := container.Create(ctx, t, client, container.WithImage(img))
+ defer client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{})
+
+ inspect, err := client.ContainerInspect(ctx, id)
+ assert.NilError(t, err)
+
+ assert.Assert(t, cmp.Len(inspect.Mounts, 1))
+
+ volumeName := inspect.Mounts[0].Name
+ assert.Assert(t, volumeName != "")
+
+ err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{})
+ assert.NilError(t, err)
+
+ pruneReport, err := client.VolumesPrune(ctx, filters.Args{})
+ assert.NilError(t, err)
+ assert.Assert(t, cmp.Contains(pruneReport.VolumesDeleted, volumeName))
+}