Skip to content

Commit

Permalink
Merge branch '1887-allow_ro_volumes-from' of https://github.com/danie…
Browse files Browse the repository at this point in the history
…l-garcia/docker into daniel-garcia-1887-allow_ro_volumes-from
  • Loading branch information
vieux committed Nov 8, 2013
2 parents 4f8b6c3 + f9cb6ae commit f417c4b
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 6 deletions.
24 changes: 19 additions & 5 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")

var flVolumesFrom utils.ListOpts
cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container")
cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)")

flEntrypoint := cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")

Expand Down Expand Up @@ -763,9 +763,23 @@ func (container *Container) Start() (err error) {

// Apply volumes from another container if requested
if container.Config.VolumesFrom != "" {
volumes := strings.Split(container.Config.VolumesFrom, ",")
for _, v := range volumes {
c := container.runtime.Get(v)
containerSpecs := strings.Split(container.Config.VolumesFrom, ",")
for _, containerSpec := range containerSpecs {
mountRW := true
specParts := strings.SplitN(containerSpec, ":", 2)
switch len(specParts) {
case 0:
return fmt.Errorf("Malformed volumes-from specification: %s", container.Config.VolumesFrom)
case 2:
switch specParts[1] {
case "ro":
mountRW = false
case "rw": // mountRW is already true
default:
return fmt.Errorf("Malformed volumes-from speficication: %s", containerSpec)
}
}
c := container.runtime.Get(specParts[0])
if c == nil {
return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
}
Expand All @@ -778,7 +792,7 @@ func (container *Container) Start() (err error) {
}
container.Volumes[volPath] = id
if isRW, exists := c.VolumesRW[volPath]; exists {
container.VolumesRW[volPath] = isRW
container.VolumesRW[volPath] = isRW && mountRW
}
}

Expand Down
61 changes: 61 additions & 0 deletions container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,67 @@ func TestBindMounts(t *testing.T) {
}
}

// Test that -volumes-from supports both read-only mounts
func TestFromVolumesInReadonlyMode(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, _, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"},
Volumes: map[string]struct{}{"/test": {}},
},
"",
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
_, err = container.Output()
if err != nil {
t.Fatal(err)
}
if !container.VolumesRW["/test"] {
t.Fail()
}

container2, _, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"},
VolumesFrom: container.ID + ":ro",
},
"",
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container2)

_, err = container2.Output()
if err != nil {
t.Fatal(err)
}

if container.Volumes["/test"] != container2.Volumes["/test"] {
t.Logf("container volumes do not match: %s | %s ",
container.Volumes["/test"],
container2.Volumes["/test"])
t.Fail()
}

_, exists := container2.VolumesRW["/test"]
if !exists {
t.Logf("container2 is missing '/test' volume: %s", container2.VolumesRW)
t.Fail()
}

if container2.VolumesRW["/test"] != false {
t.Log("'/test' volume mounted in read-write mode, expected read-only")
t.Fail()
}
}

// Test that VolumesRW values are copied to the new container. Regression test for #1201
func TestVolumesFromReadonlyMount(t *testing.T) {
runtime := mkRuntime(t)
Expand Down
13 changes: 12 additions & 1 deletion docs/sources/commandline/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ network communication.
-u="": Username or UID
-dns=[]: Set custom dns servers for the container
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume.
-volumes-from="": Mount all volumes from the given container
-volumes-from="": Mount all volumes from the given container(s)
-entrypoint="": Overwrite the default entrypoint set by the image
-w="": Working directory inside the container
-lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
Expand Down Expand Up @@ -740,6 +740,17 @@ can access the network and environment of the redis container via
environment variables. The ``-name`` flag will assign the name ``console``
to the newly created container.

.. code-block:: bash
docker run -volumes-from 777f7dc92da7,ba8c0c54f0f2:ro -i -t ubuntu pwd
The ``-volumes-from`` flag mounts all the defined volumes from the
refrence containers. Containers can be specified by a comma seperated
list or by repetitions of the ``-volumes-from`` argument. The container
id may be optionally suffixed with ``:ro`` or ``:rw`` to mount the volumes in
read-only or read-write mode, respectively. By default, the volumes are mounted
in the same mode (rw or ro) as the reference container.

.. _cli_search:

``search``
Expand Down

0 comments on commit f417c4b

Please sign in to comment.