Skip to content

Commit 45ed6a7

Browse files
committedNov 9, 2016
opts/mount: add tmpfs-specific options
added following options: * tmpfs-size * tmpfs-mode Signed-off-by: Akihiro Suda <[email protected]>
1 parent 383a2f0 commit 45ed6a7

File tree

4 files changed

+75
-8
lines changed

4 files changed

+75
-8
lines changed
 

‎docs/reference/commandline/run.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ Docker daemon.
264264

265265
For in-depth information about volumes, refer to [manage data in containers](https://docs.docker.com/engine/tutorials/dockervolumes/)
266266

267-
### Add bin-mounts or volumes using the --mounts flag
267+
### Add bin-mounts or volumes using the --mount flag
268268

269-
The `--mounts` flag allows you to mount volumes, host-directories and `tmpfs`
269+
The `--mount` flag allows you to mount volumes, host-directories and `tmpfs`
270270
mounts in a container.
271271

272272
The `--mount` flag supports most options that are supported by the `-v` or the

‎docs/reference/commandline/service_create.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ or write from files or directories on other containers or the host operating
172172
system. These types are _data volumes_ (often referred to simply as volumes) and
173173
_bind-mounts_.
174174

175+
Additionally, Docker also supports tmpfs mounts.
176+
175177
A **bind-mount** makes a file or directory on the host available to the
176178
container it is mounted within. A bind-mount may be either read-only or
177179
read-write. For example, a container might share its host's DNS information by
@@ -188,6 +190,8 @@ shared between a container and the host machine, as well as between multiple
188190
containers. Docker uses a _volume driver_ to create, manage, and mount volumes.
189191
You can back up or restore volumes using Docker commands.
190192

193+
A **tmpfs** mounts a tmpfs inside a container for volatile data.
194+
191195
Consider a situation where your image starts a lightweight web server. You could
192196
use that image as a base image, copy in your website's HTML files, and package
193197
that into another image. Each time your website changed, you'd need to update
@@ -204,8 +208,8 @@ volumes in a service:
204208

205209
| Option | Required | Description
206210
|:-----------------------------------------|:--------------------------|:-----------------------------------------------------------------------------------------
207-
| **type** | | The type of mount, can be either `volume`, or `bind`. Defaults to `volume` if no type is specified.<ul><li>`volume`: mounts a [managed volume](volume_create.md) into the container.</li><li>`bind`: bind-mounts a directory or file from the host into the container.</li></ul>
208-
| **src** or **source** | for `type=bind`&nbsp;only | <ul><li>`type=volume`: `src` is an optional way to specify the name of the volume (for example, `src=my-volume`). If the named volume does not exist, it is automatically created. If no `src` is specified, the volume is assigned a random name which is guaranteed to be unique on the host, but may not be unique cluster-wide. A randomly-named volume has the same lifecycle as its container and is destroyed when the *container* is destroyed (which is upon `service update`, or when scaling or re-balancing the service).</li><li>`type=bind`: `src` is required, and specifies an absolute path to the file or directory to bind-mount (for example, `src=/path/on/host/`). An error is produced if the file or directory does not exist.</li></ul>
211+
| **type** | | The type of mount, can be either `volume`, `bind`, or `tmpfs`. Defaults to `volume` if no type is specified.<ul><li>`volume`: mounts a [managed volume](volume_create.md) into the container.</li><li>`bind`: bind-mounts a directory or file from the host into the container.</li><li>`tmpfs`: mount a tmpfs in the container</li></ul>
212+
| **src** or **source** | for `type=bind`&nbsp;only | <ul><li>`type=volume`: `src` is an optional way to specify the name of the volume (for example, `src=my-volume`). If the named volume does not exist, it is automatically created. If no `src` is specified, the volume is assigned a random name which is guaranteed to be unique on the host, but may not be unique cluster-wide. A randomly-named volume has the same lifecycle as its container and is destroyed when the *container* is destroyed (which is upon `service update`, or when scaling or re-balancing the service).</li><li>`type=bind`: `src` is required, and specifies an absolute path to the file or directory to bind-mount (for example, `src=/path/on/host/`). An error is produced if the file or directory does not exist.</li><li>`type=tmpfs`: `src` is not supported.</li></ul>
209213
| **dst** or **destination** or **target** | yes | Mount path inside the container, for example `/some/path/in/container/`. If the path does not exist in the container's filesystem, the Engine creates a directory at the specified location before mounting the volume or bind-mount.
210214
| **readonly** or **ro** | | The Engine mounts binds and volumes `read-write` unless `readonly` option is given when mounting the bind or volume.<br /><br /><ul><li>`true` or `1` or no value: Mounts the bind or volume read-only.</li><li>`false` or `0`: Mounts the bind or volume read-write.</li></ul>
211215

@@ -256,6 +260,14 @@ The following options can only be used for named volumes (`type=volume`);
256260
| **volume-nocopy** | By default, if you attach an empty volume to a container, and files or directories already existed at the mount-path in the container (`dst`), the Engine copies those files and directories into the volume, allowing the host to access them. Set `volume-nocopy` to disables copying files from the container's filesystem to the volume and mount the empty volume.<br /><br />A value is optional:<ul><li>`true` or `1`: Default if you do not provide a value. Disables copying.</li><li>`false` or `0`: Enables copying.</li></ul>
257261
| **volume-opt** | Options specific to a given volume driver, which will be passed to the driver when creating the volume. Options are provided as a comma-separated list of key/value pairs, for example, `volume-opt=some-option=some-value,some-other-option=some-other-value`. For available options for a given driver, refer to that driver's documentation.
258262

263+
#### Options for tmpfs
264+
The following options can only be used for tmpfs mounts (`type=tmpfs`);
265+
266+
| Option | Description
267+
|:----------------------|:--------------------------------------------------------------------------------------------------------------------
268+
| **tmpfs-size** | Size of the tmpfs mount in bytes. Unlimited by default in Linux.
269+
| **tmpfs-mode** | File mode of the tmpfs in octal. (e.g. `"700"` or `"0700"`.) Defaults to ``"1777"`` in Linux.
270+
259271
#### Differences between "--mount" and "--volume"
260272

261273
The `--mount` flag supports most options that are supported by the `-v`

‎opts/mount.go

+28-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package opts
33
import (
44
"encoding/csv"
55
"fmt"
6+
"os"
67
"strconv"
78
"strings"
89

910
mounttypes "github.com/docker/docker/api/types/mount"
11+
"github.com/docker/go-units"
1012
)
1113

1214
// MountOpt is a Value type for parsing mounts
@@ -43,6 +45,13 @@ func (m *MountOpt) Set(value string) error {
4345
return mount.BindOptions
4446
}
4547

48+
tmpfsOptions := func() *mounttypes.TmpfsOptions {
49+
if mount.TmpfsOptions == nil {
50+
mount.TmpfsOptions = new(mounttypes.TmpfsOptions)
51+
}
52+
return mount.TmpfsOptions
53+
}
54+
4655
setValueOnMap := func(target map[string]string, value string) {
4756
parts := strings.SplitN(value, "=", 2)
4857
if len(parts) == 1 {
@@ -102,6 +111,18 @@ func (m *MountOpt) Set(value string) error {
102111
volumeOptions().DriverConfig.Options = make(map[string]string)
103112
}
104113
setValueOnMap(volumeOptions().DriverConfig.Options, value)
114+
case "tmpfs-size":
115+
sizeBytes, err := units.RAMInBytes(value)
116+
if err != nil {
117+
return fmt.Errorf("invalid value for %s: %s", key, value)
118+
}
119+
tmpfsOptions().SizeBytes = sizeBytes
120+
case "tmpfs-mode":
121+
ui64, err := strconv.ParseUint(value, 8, 32)
122+
if err != nil {
123+
return fmt.Errorf("invalid value for %s: %s", key, value)
124+
}
125+
tmpfsOptions().Mode = os.FileMode(ui64)
105126
default:
106127
return fmt.Errorf("unexpected key '%s' in '%s'", key, field)
107128
}
@@ -115,11 +136,14 @@ func (m *MountOpt) Set(value string) error {
115136
return fmt.Errorf("target is required")
116137
}
117138

118-
if mount.Type == mounttypes.TypeBind && mount.VolumeOptions != nil {
119-
return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", mounttypes.TypeBind)
139+
if mount.VolumeOptions != nil && mount.Type != mounttypes.TypeVolume {
140+
return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", mount.Type)
141+
}
142+
if mount.BindOptions != nil && mount.Type != mounttypes.TypeBind {
143+
return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", mount.Type)
120144
}
121-
if mount.Type == mounttypes.TypeVolume && mount.BindOptions != nil {
122-
return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", mounttypes.TypeVolume)
145+
if mount.TmpfsOptions != nil && mount.Type != mounttypes.TypeTmpfs {
146+
return fmt.Errorf("cannot mix 'tmpfs-*' options with mount type '%s'", mount.Type)
123147
}
124148

125149
m.values = append(m.values, mount)

‎opts/mount_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package opts
22

33
import (
4+
"os"
45
"testing"
56

67
mounttypes "github.com/docker/docker/api/types/mount"
@@ -151,3 +152,33 @@ func TestMountOptTypeConflict(t *testing.T) {
151152
assert.Error(t, m.Set("type=bind,target=/foo,source=/foo,volume-nocopy=true"), "cannot mix")
152153
assert.Error(t, m.Set("type=volume,target=/foo,source=/foo,bind-propagation=rprivate"), "cannot mix")
153154
}
155+
156+
func TestMountOptSetTmpfsNoError(t *testing.T) {
157+
for _, testcase := range []string{
158+
// tests several aliases that should have same result.
159+
"type=tmpfs,target=/target,tmpfs-size=1m,tmpfs-mode=0700",
160+
"type=tmpfs,target=/target,tmpfs-size=1MB,tmpfs-mode=700",
161+
} {
162+
var mount MountOpt
163+
164+
assert.NilError(t, mount.Set(testcase))
165+
166+
mounts := mount.Value()
167+
assert.Equal(t, len(mounts), 1)
168+
assert.DeepEqual(t, mounts[0], mounttypes.Mount{
169+
Type: mounttypes.TypeTmpfs,
170+
Target: "/target",
171+
TmpfsOptions: &mounttypes.TmpfsOptions{
172+
SizeBytes: 1024 * 1024, // not 1000 * 1000
173+
Mode: os.FileMode(0700),
174+
},
175+
})
176+
}
177+
}
178+
179+
func TestMountOptSetTmpfsError(t *testing.T) {
180+
var m MountOpt
181+
assert.Error(t, m.Set("type=tmpfs,target=/foo,tmpfs-size=foo"), "invalid value for tmpfs-size")
182+
assert.Error(t, m.Set("type=tmpfs,target=/foo,tmpfs-mode=foo"), "invalid value for tmpfs-mode")
183+
assert.Error(t, m.Set("type=tmpfs"), "target is required")
184+
}

0 commit comments

Comments
 (0)
Please sign in to comment.