mirror of https://github.com/docker/compose.git
Fix bind mounts when in project volumes definition
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
This commit is contained in:
parent
6756732fe4
commit
919f351b4b
|
@ -718,9 +718,15 @@ MOUNTS:
|
||||||
// so `Bind` API is used here with raw volume string
|
// so `Bind` API is used here with raw volume string
|
||||||
// see https://github.com/moby/moby/issues/43483
|
// see https://github.com/moby/moby/issues/43483
|
||||||
for _, v := range service.Volumes {
|
for _, v := range service.Volumes {
|
||||||
if v.Target == m.Target && v.Bind != nil && v.Bind.CreateHostPath {
|
if v.Target == m.Target {
|
||||||
binds = append(binds, v.String())
|
switch {
|
||||||
continue MOUNTS
|
case string(m.Type) != v.Type:
|
||||||
|
v.Source = m.Source
|
||||||
|
fallthrough
|
||||||
|
case v.Bind != nil && v.Bind.CreateHostPath:
|
||||||
|
binds = append(binds, v.String())
|
||||||
|
continue MOUNTS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -911,10 +917,14 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bind, vol, tmpfs := buildMountOptions(volume)
|
bind, vol, tmpfs := buildMountOptions(project, volume)
|
||||||
|
|
||||||
volume.Target = path.Clean(volume.Target)
|
volume.Target = path.Clean(volume.Target)
|
||||||
|
|
||||||
|
if bind != nil {
|
||||||
|
volume.Type = types.VolumeTypeBind
|
||||||
|
}
|
||||||
|
|
||||||
return mount.Mount{
|
return mount.Mount{
|
||||||
Type: mount.Type(volume.Type),
|
Type: mount.Type(volume.Type),
|
||||||
Source: source,
|
Source: source,
|
||||||
|
@ -927,7 +937,7 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildMountOptions(volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions) {
|
func buildMountOptions(project types.Project, volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions) {
|
||||||
switch volume.Type {
|
switch volume.Type {
|
||||||
case "bind":
|
case "bind":
|
||||||
if volume.Volume != nil {
|
if volume.Volume != nil {
|
||||||
|
@ -944,6 +954,11 @@ func buildMountOptions(volume types.ServiceVolumeConfig) (*mount.BindOptions, *m
|
||||||
if volume.Tmpfs != nil {
|
if volume.Tmpfs != nil {
|
||||||
logrus.Warnf("mount of type `volume` should not define `tmpfs` option")
|
logrus.Warnf("mount of type `volume` should not define `tmpfs` option")
|
||||||
}
|
}
|
||||||
|
if v, ok := project.Volumes[volume.Source]; ok && v.DriverOpts["o"] == types.VolumeTypeBind {
|
||||||
|
return buildBindOption(&types.ServiceVolumeBind{
|
||||||
|
CreateHostPath: true,
|
||||||
|
}), nil, nil
|
||||||
|
}
|
||||||
return nil, buildVolumeOptions(volume.Volume), nil
|
return nil, buildVolumeOptions(volume.Volume), nil
|
||||||
case "tmpfs":
|
case "tmpfs":
|
||||||
if volume.Bind != nil {
|
if volume.Bind != nil {
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: nginx
|
||||||
|
container_name: frontend
|
||||||
|
volumes:
|
||||||
|
- project_data:/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
project_data:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: "${TEST_DIR}"
|
|
@ -167,6 +167,19 @@ func (c *E2eCLI) NewCmd(command string, args ...string) icmd.Cmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCmdWithEnv creates a cmd object configured with the test environment set with additional env vars
|
||||||
|
func (c *E2eCLI) NewCmdWithEnv(envvars []string, command string, args ...string) icmd.Cmd {
|
||||||
|
env := append(os.Environ(),
|
||||||
|
append(envvars,
|
||||||
|
"DOCKER_CONFIG="+c.ConfigDir,
|
||||||
|
"KUBECONFIG=invalid")...,
|
||||||
|
)
|
||||||
|
return icmd.Cmd{
|
||||||
|
Command: append([]string{command}, args...),
|
||||||
|
Env: env,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MetricsSocket get the path where test metrics will be sent
|
// MetricsSocket get the path where test metrics will be sent
|
||||||
func (c *E2eCLI) MetricsSocket() string {
|
func (c *E2eCLI) MetricsSocket() string {
|
||||||
return filepath.Join(c.ConfigDir, "./docker-cli.sock")
|
return filepath.Join(c.ConfigDir, "./docker-cli.sock")
|
||||||
|
|
|
@ -18,11 +18,14 @@ package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
|
"gotest.tools/v3/icmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLocalComposeVolume(t *testing.T) {
|
func TestLocalComposeVolume(t *testing.T) {
|
||||||
|
@ -88,3 +91,30 @@ func TestLocalComposeVolume(t *testing.T) {
|
||||||
assert.Assert(t, !strings.Contains(ls, "myvolume"))
|
assert.Assert(t, !strings.Contains(ls, "myvolume"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProjectVolumeBind(t *testing.T) {
|
||||||
|
if composeStandaloneMode {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
c := NewParallelE2eCLI(t, binDir)
|
||||||
|
const projectName = "compose-e2e-project-volume-bind"
|
||||||
|
|
||||||
|
t.Run("up on project volume with bind specification", func(t *testing.T) {
|
||||||
|
tmpDir, err := os.MkdirTemp("", projectName)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir) // nolint
|
||||||
|
|
||||||
|
c.RunDockerComposeCmd("--project-name", projectName, "down")
|
||||||
|
|
||||||
|
c.RunDockerOrExitError("volume", "rm", "-f", projectName+"_project_data").Assert(t, icmd.Success)
|
||||||
|
cmd := c.NewCmdWithEnv([]string{"TEST_DIR=" + tmpDir},
|
||||||
|
"docker", "compose", "--project-directory", "fixtures/project-volume-bind-test", "--project-name", projectName, "up", "-d")
|
||||||
|
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||||
|
defer c.RunDockerComposeCmd("--project-name", projectName, "down")
|
||||||
|
|
||||||
|
c.RunCmd("sh", "-c", "echo SUCCESS > "+filepath.Join(tmpDir, "resultfile")).Assert(t, icmd.Success)
|
||||||
|
|
||||||
|
ret := c.RunDockerOrExitError("exec", "frontend", "bash", "-c", "cat /data/resultfile").Assert(t, icmd.Success)
|
||||||
|
assert.Assert(t, strings.Contains(ret.Stdout(), "SUCCESS"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue