mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #14659 from calavera/promote_volumes_experimental_to_master
Promote volume drivers from experimental to master.
This commit is contained in:
commit
3ee15acaad
13 changed files with 107 additions and 193 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
"github.com/docker/docker/volume"
|
"github.com/docker/docker/volume"
|
||||||
|
"github.com/docker/docker/volume/drivers"
|
||||||
"github.com/docker/docker/volume/local"
|
"github.com/docker/docker/volume/local"
|
||||||
"github.com/opencontainers/runc/libcontainer/label"
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
)
|
)
|
||||||
|
@ -333,3 +334,18 @@ func removeVolume(v volume.Volume) error {
|
||||||
}
|
}
|
||||||
return vd.Remove(v)
|
return vd.Remove(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getVolumeDriver(name string) (volume.Driver, error) {
|
||||||
|
if name == "" {
|
||||||
|
name = volume.DefaultDriverName
|
||||||
|
}
|
||||||
|
return volumedrivers.Lookup(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseVolumeSource(spec string) (string, string, error) {
|
||||||
|
if !filepath.IsAbs(spec) {
|
||||||
|
return spec, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", spec, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
// +build experimental
|
|
||||||
|
|
||||||
package daemon
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/docker/docker/volume"
|
|
||||||
"github.com/docker/docker/volume/drivers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getVolumeDriver(name string) (volume.Driver, error) {
|
|
||||||
if name == "" {
|
|
||||||
name = volume.DefaultDriverName
|
|
||||||
}
|
|
||||||
return volumedrivers.Lookup(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseVolumeSource(spec string) (string, string, error) {
|
|
||||||
if !filepath.IsAbs(spec) {
|
|
||||||
return spec, "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", spec, nil
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// +build !experimental
|
|
||||||
|
|
||||||
package daemon
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/docker/docker/volume"
|
|
||||||
"github.com/docker/docker/volume/drivers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getVolumeDriver(_ string) (volume.Driver, error) {
|
|
||||||
return volumedrivers.Lookup(volume.DefaultDriverName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseVolumeSource(spec string) (string, string, error) {
|
|
||||||
if !filepath.IsAbs(spec) {
|
|
||||||
return "", "", fmt.Errorf("cannot bind mount volume: %s volume paths must be absolute.", spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", spec, nil
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
// +build !experimental
|
|
||||||
|
|
||||||
package daemon
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/docker/docker/runconfig"
|
|
||||||
"github.com/docker/docker/volume"
|
|
||||||
"github.com/docker/docker/volume/drivers"
|
|
||||||
"github.com/docker/docker/volume/local"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetVolumeDefaultDriver(t *testing.T) {
|
|
||||||
tmp, err := ioutil.TempDir("", "volume-test-")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmp)
|
|
||||||
|
|
||||||
l, err := local.New(tmp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
volumedrivers.Register(l, volume.DefaultDriverName)
|
|
||||||
d, err := getVolumeDriver("missing")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.Name() != volume.DefaultDriverName {
|
|
||||||
t.Fatalf("Expected local driver, was %s\n", d.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseBindMount(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
bind string
|
|
||||||
expDest string
|
|
||||||
expSource string
|
|
||||||
expName string
|
|
||||||
mountLabel string
|
|
||||||
expRW bool
|
|
||||||
fail bool
|
|
||||||
}{
|
|
||||||
{"/tmp:/tmp", "/tmp", "/tmp", "", "", true, false},
|
|
||||||
{"/tmp:/tmp:ro", "/tmp", "/tmp", "", "", false, false},
|
|
||||||
{"/tmp:/tmp:rw", "/tmp", "/tmp", "", "", true, false},
|
|
||||||
{"/tmp:/tmp:foo", "/tmp", "/tmp", "", "", false, true},
|
|
||||||
{"name:/tmp", "", "", "", "", false, true},
|
|
||||||
{"local/name:/tmp:rw", "", "", "", "", true, true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range cases {
|
|
||||||
conf := &runconfig.Config{}
|
|
||||||
m, err := parseBindMount(c.bind, c.mountLabel, conf)
|
|
||||||
if c.fail {
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Destination != c.expDest {
|
|
||||||
t.Fatalf("Expected destination %s, was %s, for spec %s\n", c.expDest, m.Destination, c.bind)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Source != c.expSource {
|
|
||||||
t.Fatalf("Expected source %s, was %s, for spec %s\n", c.expSource, m.Source, c.bind)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Name != c.expName {
|
|
||||||
t.Fatalf("Expected name %s, was %s for spec %s\n", c.expName, m.Name, c.bind)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.RW != c.expRW {
|
|
||||||
t.Fatalf("Expected RW %v, was %v for spec %s\n", c.expRW, m.RW, c.bind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
22
docs/extend/index.md
Normal file
22
docs/extend/index.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "Extend Docker"
|
||||||
|
description = "How to extend Docker with plugins"
|
||||||
|
keywords = ["extend, plugins, docker, documentation, developer"]
|
||||||
|
[menu.main]
|
||||||
|
identifier = "mn_extend"
|
||||||
|
name = "Extend Docker"
|
||||||
|
weight = 6
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
|
||||||
|
## Extending Docker
|
||||||
|
|
||||||
|
Currently, you can extend Docker by adding a plugin. This section contains the following topics:
|
||||||
|
|
||||||
|
* [Understand Docker plugins](plugins.md)
|
||||||
|
* [Write a volume plugin](plugins_volumes.md)
|
||||||
|
* [Docker plugin API](plugin_api.md)
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
# Experimental: Docker Plugin API
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "Plugins API"
|
||||||
|
description = "How to write Docker plugins extensions "
|
||||||
|
keywords = ["API, Usage, plugins, documentation, developer"]
|
||||||
|
[menu.main]
|
||||||
|
parent = "mn_extend"
|
||||||
|
weight=1
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
# Docker Plugin API
|
||||||
|
|
||||||
Docker plugins are out-of-process extensions which add capabilities to the
|
Docker plugins are out-of-process extensions which add capabilities to the
|
||||||
Docker Engine.
|
Docker Engine.
|
||||||
|
|
||||||
This page is intended for people who want to develop their own Docker plugin.
|
This page is intended for people who want to develop their own Docker plugin.
|
||||||
If you just want to learn about or use Docker plugins, look
|
If you just want to learn about or use Docker plugins, look
|
||||||
[here](/experimental/plugins.md).
|
[here](plugins.md).
|
||||||
|
|
||||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
|
||||||
|
|
||||||
## What plugins are
|
## What plugins are
|
||||||
|
|
||||||
|
@ -77,10 +86,6 @@ manage startup and shutdown order.
|
||||||
When upgrading a plugin, you should first stop the Docker daemon, upgrade the
|
When upgrading a plugin, you should first stop the Docker daemon, upgrade the
|
||||||
plugin, then start Docker again.
|
plugin, then start Docker again.
|
||||||
|
|
||||||
If a plugin is packaged as a container, this may cause issues. Plugins as
|
|
||||||
containers are currently considered experimental due to these shutdown/startup
|
|
||||||
ordering issues. These issues are mitigated by plugin retries (see below).
|
|
||||||
|
|
||||||
## Plugin activation
|
## Plugin activation
|
||||||
|
|
||||||
When a plugin is first referred to -- either by a user referring to it by name
|
When a plugin is first referred to -- either by a user referring to it by name
|
|
@ -1,14 +1,23 @@
|
||||||
# Experimental: Extend Docker with a plugin
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "Extending Docker with plugins"
|
||||||
|
description = "How to add additional functionality to Docker with plugins extensions"
|
||||||
|
keywords = ["Examples, Usage, plugins, docker, documentation, user guide"]
|
||||||
|
[menu.main]
|
||||||
|
parent = "mn_extend"
|
||||||
|
weight=-1
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
# Understand Docker plugins
|
||||||
|
|
||||||
You can extend the capabilities of the Docker Engine by loading third-party
|
You can extend the capabilities of the Docker Engine by loading third-party
|
||||||
plugins.
|
plugins.
|
||||||
|
|
||||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
|
||||||
|
|
||||||
## Types of plugins
|
## Types of plugins
|
||||||
|
|
||||||
Plugins extend Docker's functionality. They come in specific types. For
|
Plugins extend Docker's functionality. They come in specific types. For
|
||||||
example, a [volume plugin](/experimental/plugins_volume.md) might enable Docker
|
example, a [volume plugin](plugins_volume.md) might enable Docker
|
||||||
volumes to persist across multiple Docker hosts.
|
volumes to persist across multiple Docker hosts.
|
||||||
|
|
||||||
Currently Docker supports volume and network driver plugins. In the future it
|
Currently Docker supports volume and network driver plugins. In the future it
|
||||||
|
@ -27,12 +36,13 @@ The following plugins exist:
|
||||||
databases and other stateful containers and move them around across a cluster
|
databases and other stateful containers and move them around across a cluster
|
||||||
of machines.
|
of machines.
|
||||||
|
|
||||||
* The [Weave plugin](https://github.com/weaveworks/docker-plugin) is a network
|
* The [GlusterFS plugin](https://github.com/calavera/docker-volume-glusterfs) is
|
||||||
driver plugin which provides a virtual, multi-host network for containers.
|
another volume plugin that provides multi-host volumes management for Docker
|
||||||
|
using GlusterFS.
|
||||||
|
|
||||||
* The [Calico plugin](https://github.com/metaswitch/calico-docker) is a network
|
* The [Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) is
|
||||||
driver plugin which provides a multi-host network for containers with routes
|
a plugin that provides credentials and secret management using Keywhiz as
|
||||||
distributed by BGP.
|
a central repository.
|
||||||
|
|
||||||
## Troubleshooting a plugin
|
## Troubleshooting a plugin
|
||||||
|
|
||||||
|
@ -42,11 +52,4 @@ of the plugin for help. The Docker team may not be able to assist you.
|
||||||
## Writing a plugin
|
## Writing a plugin
|
||||||
|
|
||||||
If you are interested in writing a plugin for Docker, or seeing how they work
|
If you are interested in writing a plugin for Docker, or seeing how they work
|
||||||
under the hood, see the [docker plugins reference](/experimental/plugin_api.md).
|
under the hood, see the [docker plugins reference](plugin_api.md).
|
||||||
|
|
||||||
# Related GitHub PRs and issues
|
|
||||||
|
|
||||||
- [#13222](https://github.com/docker/docker/pull/13222) Plugins plumbing
|
|
||||||
|
|
||||||
Send us feedback and comments on [#13419](https://github.com/docker/docker/issues/13419),
|
|
||||||
or on the usual Google Groups (docker-user, docker-dev) and IRC channels.
|
|
|
@ -1,34 +1,38 @@
|
||||||
# Experimental: Docker volume plugins
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "Volume plugins"
|
||||||
|
description = "How to manage data with external volume plugins"
|
||||||
|
keywords = ["Examples, Usage, volume, docker, data, volumes, plugin, api"]
|
||||||
|
[menu.main]
|
||||||
|
parent = "mn_extend"
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
# Write a volume plugin
|
||||||
|
|
||||||
Docker volume plugins enable Docker deployments to be integrated with external
|
Docker volume plugins enable Docker deployments to be integrated with external
|
||||||
storage systems, such as Amazon EBS, and enable data volumes to persist beyond
|
storage systems, such as Amazon EBS, and enable data volumes to persist beyond
|
||||||
the lifetime of a single Docker host. See the [plugin documentation](/experimental/plugins.md)
|
the lifetime of a single Docker host. See the [plugin documentation](plugins.md)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
|
||||||
|
|
||||||
# Command-line changes
|
# Command-line changes
|
||||||
|
|
||||||
This experimental feature introduces two changes to the `docker run` command:
|
A volume plugin makes use of the `-v`and `--volume-driver` flag on the `docker run` command. The `-v` flag accepts a volume name and the `--volume-driver` flag a driver type, for example:
|
||||||
|
|
||||||
- The `--volume-driver` flag is introduced.
|
$ docker run -ti -v volumename:/data --volume-driver=flocker busybox sh
|
||||||
- The `-v` syntax is changed to accept a volume name a first component.
|
|
||||||
|
|
||||||
Example:
|
This command passes the `volumename` through to the volume plugin as a
|
||||||
|
user-given name for the volume. The `volumename` must not begin with a `/`.
|
||||||
|
|
||||||
$ docker run -ti -v volumename:/data --volume-driver=flocker busybox sh
|
By having the user specify a `volumename`, a plugin can associate the volume
|
||||||
|
with an external volume beyond the lifetime of a single container or container
|
||||||
|
host. This can be used, for example, to move a stateful container from one
|
||||||
|
server to another.
|
||||||
|
|
||||||
By specifying a volume name in conjunction with a volume driver, volume plugins
|
By specifying a `volumedriver` in conjunction with a `volumename`, users can use plugins such as [Flocker](https://clusterhq.com/docker-plugin/) to manage volumes external to a single host, such as those on EBS.
|
||||||
such as [Flocker](https://clusterhq.com/docker-plugin/), once installed, can be
|
|
||||||
used to manage volumes external to a single host, such as those on EBS. In this
|
|
||||||
example, "volumename" is passed through to the volume plugin as a user-given
|
|
||||||
name for the volume which allows the plugin to associate it with an external
|
|
||||||
volume beyond the lifetime of a single container or container host. This can be
|
|
||||||
used, for example, to move a stateful container from one server to another.
|
|
||||||
|
|
||||||
The `volumename` must not begin with a `/`.
|
|
||||||
|
|
||||||
# API changes
|
# Create a VolumeDriver
|
||||||
|
|
||||||
The container creation endpoint (`/containers/create`) accepts a `VolumeDriver`
|
The container creation endpoint (`/containers/create`) accepts a `VolumeDriver`
|
||||||
field of type `string` allowing to specify the name of the driver. It's default
|
field of type `string` allowing to specify the name of the driver. It's default
|
||||||
|
@ -152,9 +156,3 @@ this point.
|
||||||
|
|
||||||
Respond with a string error if an error occurred.
|
Respond with a string error if an error occurred.
|
||||||
|
|
||||||
# Related GitHub PRs and issues
|
|
||||||
|
|
||||||
- [#13161](https://github.com/docker/docker/pull/13161) Volume refactor and external volume plugins
|
|
||||||
|
|
||||||
Send us feedback and comments on [#13420](https://github.com/docker/docker/issues/13420),
|
|
||||||
or on the usual Google Groups (docker-user, docker-dev) and IRC channels.
|
|
|
@ -18,7 +18,7 @@ commands. For example,
|
||||||
|
|
||||||
docker network create -d weave mynet
|
docker network create -d weave mynet
|
||||||
|
|
||||||
Some network driver plugins are listed in [plugins.md](plugins.md)
|
Some network driver plugins are listed in [plugins.md](/docs/extend/plugins.md)
|
||||||
|
|
||||||
The network thus created is owned by the plugin, so subsequent commands
|
The network thus created is owned by the plugin, so subsequent commands
|
||||||
referring to that network will also be run through the plugin.
|
referring to that network will also be run through the plugin.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// +build experimental
|
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
|
@ -26,15 +26,16 @@ var (
|
||||||
|
|
||||||
// validateNM is the set of fields passed to validateNetMode()
|
// validateNM is the set of fields passed to validateNetMode()
|
||||||
type validateNM struct {
|
type validateNM struct {
|
||||||
netMode NetworkMode
|
netMode NetworkMode
|
||||||
flHostname *string
|
flHostname *string
|
||||||
flLinks opts.ListOpts
|
flLinks opts.ListOpts
|
||||||
flDns opts.ListOpts
|
flDns opts.ListOpts
|
||||||
flExtraHosts opts.ListOpts
|
flExtraHosts opts.ListOpts
|
||||||
flMacAddress *string
|
flMacAddress *string
|
||||||
flPublish opts.ListOpts
|
flPublish opts.ListOpts
|
||||||
flPublishAll *bool
|
flPublishAll *bool
|
||||||
flExpose opts.ListOpts
|
flExpose opts.ListOpts
|
||||||
|
flVolumeDriver string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
|
func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||||
|
@ -94,6 +95,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
||||||
flReadonlyRootfs = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
|
flReadonlyRootfs = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
|
||||||
flLoggingDriver = cmd.String([]string{"-log-driver"}, "", "Logging driver for container")
|
flLoggingDriver = cmd.String([]string{"-log-driver"}, "", "Logging driver for container")
|
||||||
flCgroupParent = cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
|
flCgroupParent = cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
|
||||||
|
flVolumeDriver = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
|
cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
|
||||||
|
@ -332,6 +334,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
||||||
Entrypoint: entrypoint,
|
Entrypoint: entrypoint,
|
||||||
WorkingDir: *flWorkingDir,
|
WorkingDir: *flWorkingDir,
|
||||||
Labels: convertKVStringsToMap(labels),
|
Labels: convertKVStringsToMap(labels),
|
||||||
|
VolumeDriver: *flVolumeDriver,
|
||||||
}
|
}
|
||||||
|
|
||||||
hostConfig := &HostConfig{
|
hostConfig := &HostConfig{
|
||||||
|
|
|
@ -10,12 +10,10 @@ type experimentalFlags struct {
|
||||||
|
|
||||||
func attachExperimentalFlags(cmd *flag.FlagSet) *experimentalFlags {
|
func attachExperimentalFlags(cmd *flag.FlagSet) *experimentalFlags {
|
||||||
flags := make(map[string]interface{})
|
flags := make(map[string]interface{})
|
||||||
flags["volume-driver"] = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
|
|
||||||
flags["publish-service"] = cmd.String([]string{"-publish-service"}, "", "Publish this container as a service")
|
flags["publish-service"] = cmd.String([]string{"-publish-service"}, "", "Publish this container as a service")
|
||||||
return &experimentalFlags{flags: flags}
|
return &experimentalFlags{flags: flags}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyExperimentalFlags(exp *experimentalFlags, config *Config, hostConfig *HostConfig) {
|
func applyExperimentalFlags(exp *experimentalFlags, config *Config, hostConfig *HostConfig) {
|
||||||
config.VolumeDriver = *(exp.flags["volume-driver"]).(*string)
|
|
||||||
config.PublishService = *(exp.flags["publish-service"]).(*string)
|
config.PublishService = *(exp.flags["publish-service"]).(*string)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue