Merge pull request #19242 from mavenugo/nsalias

Network scoped alias support
This commit is contained in:
David Calavera 2016-01-14 10:58:51 -08:00
commit 73a5393bf3
14 changed files with 238 additions and 2 deletions

View file

@ -118,6 +118,8 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
flIPv6Address := cmd.String([]string{"-ip6"}, "", "IPv6 Address")
flLinks := opts.NewListOpts(runconfigopts.ValidateLink)
cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
flAliases := opts.NewListOpts(nil)
cmd.Var(&flAliases, []string{"-alias"}, "Add network-scoped alias for the container")
cmd.Require(flag.Min, 2)
if err := cmd.ParseFlags(args, true); err != nil {
return err
@ -127,7 +129,8 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
IPv4Address: *flIPAddress,
IPv6Address: *flIPv6Address,
},
Links: flLinks.GetAll(),
Links: flLinks.GetAll(),
Aliases: flAliases.GetAll(),
}
return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig)
}

View file

@ -284,6 +284,10 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network) ([]
createOptions = append(createOptions,
libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), nil))
}
for _, alias := range epConfig.Aliases {
createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias))
}
}
if !container.HostConfig.NetworkMode.IsUserDefined() {

View file

@ -761,6 +761,10 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
return runconfig.ErrUnsupportedNetworkAndIP
}
if !containertypes.NetworkMode(idOrName).IsUserDefined() && len(endpointConfig.Aliases) > 0 {
return runconfig.ErrUnsupportedNetworkAndAlias
}
controller := daemon.netController
if err := validateNetworkingConfig(n, endpointConfig); err != nil {

View file

@ -68,6 +68,7 @@ Creates a new container.
'container:<name|id>': reuse another container's network stack
'host': use the Docker host network stack
'<network-name>|<network-id>': connect to a user-defined network
--net-alias=[] Add network-scoped alias for the container
--oom-kill-disable Whether to disable OOM Killer for the container or not
--oom-score-adj=0 Tune the host's OOM preferences for containers (accepts -1000 to 1000)
-P, --publish-all Publish all exposed ports to random ports

View file

@ -14,6 +14,7 @@ parent = "smn_cli"
Connects a container to a network
--alias=[] Add network-scoped alias for the container
--help Print usage
--ip IPv4 Address
--ip6 IPv6 Address
@ -45,6 +46,13 @@ You can use `--link` option to link another container with a prefered alias
$ docker network connect --link container1:c1 multi-host-network container2
```
`--alias` option can be used to resolve the container by another name in the network
being connected to.
```bash
$ docker network connect --alias db --alias mysql multi-host-network container2
```
You can pause, restart, and stop containers that are connected to a network.
Paused containers remain connected and can be revealed by a `network inspect`.
When the container is stopped, it does not appear on the network until you restart

View file

@ -68,6 +68,7 @@ parent = "smn_cli"
'container:<name|id>': reuse another container's network stack
'host': use the Docker host network stack
'<network-name>|<network-id>': connect to a user-defined network
--net-alias=[] Add network-scoped alias for the container
--oom-kill-disable Whether to disable OOM Killer for the container or not
--oom-score-adj=0 Tune the host's OOM preferences for containers (accepts -1000 to 1000)
-P, --publish-all Publish all exposed ports to random ports

View file

@ -273,6 +273,7 @@ of the containers.
'container:<name|id>': reuse another container's network stack
'host': use the Docker host network stack
'<network-name>|<network-id>': connect to a user-defined network
--net-alias=[] : Add network-scoped alias for the container
--add-host="" : Add a line to /etc/hosts (host:IP)
--mac-address="" : Sets the container's Ethernet device's MAC address
--ip="" : Sets the container's Ethernet device's IPv4 address

View file

@ -502,6 +502,130 @@ environment variables into a running container without significant effort and he
it is not compatible with `docker network` which provides a dynamic way to connect/
disconnect containers to/from a network.
### Network-scoped alias
While `links` provide private name resolution that is localized within a container,
the network-scoped alias provides a way for a container to be discovered by an
alternate name by any other container within the scope of a particular network.
Unlike the `link` alias, which is defined by the consumer of a service, the
network-scoped alias is defined by the container that is offering the service
to the network.
Continuing with the above example, create another container in `isolated_nw` with a
network alias.
```bash
$ docker run --net=isolated_nw -itd --name=container6 --net-alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
```
```bash
$ docker attach container4
/ # ping -w 4 app
PING app (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
--- app ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
/ # ping -w 4 container6
PING container5 (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
--- container6 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
```
Now let us connect `container6` to the `local_alias` network with a different network-scoped
alias.
```
$ docker network connect --alias scoped-app local_alias container6
```
`container6` in this example now is aliased as `app` in network `isolated_nw` and
as `scoped-app` in network `local_alias`.
Let's try to reach these aliases from `container4` (which is connected to both these networks)
and `container5` (which is connected only to `isolated_nw`).
```bash
$ docker attach container4
/ # ping -w 4 scoped-app
PING foo (172.26.0.5): 56 data bytes
64 bytes from 172.26.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.5: seq=3 ttl=64 time=0.097 ms
--- foo ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
$ docker attach container5
/ # ping -w 4 scoped-app
ping: bad address 'scoped-app'
```
As you can see, the alias is scoped to the network it is defined on and hence only
those containers that are connected to that network can access the alias.
In addition to the above features, multiple containers can share the same network-scoped
alias within the same network. For example, let's launch `container7` in `isolated_nw` with
the same alias as `container6`
```bash
$ docker run --net=isolated_nw -itd --name=container7 --net-alias app busybox
3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554
```
When multiple containers share the same alias, name resolution to that alias will happen
to one of the containers (typically the first container that is aliased). When the container
that backs the alias goes down or disconnected from the network, the next container that
backs the alias will be resolved.
Let us ping the alias `app` from `container4` and bring down `container6` to verify that
`container7` is resolving the `app` alias.
```bash
$ docker attach container4
/ # ping -w 4 app
PING app (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
--- app ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
$ docker stop container6
$ docker attach container4
/ # ping -w 4 app
PING app (172.25.0.7): 56 data bytes
64 bytes from 172.25.0.7: seq=0 ttl=64 time=0.095 ms
64 bytes from 172.25.0.7: seq=1 ttl=64 time=0.075 ms
64 bytes from 172.25.0.7: seq=2 ttl=64 time=0.072 ms
64 bytes from 172.25.0.7: seq=3 ttl=64 time=0.101 ms
--- app ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.072/0.085/0.101 ms
```
## Disconnecting containers

View file

@ -1138,5 +1138,42 @@ func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) {
c.Assert(networks, checker.Contains, netWorkName1, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName1)))
c.Assert(networks, checker.Contains, netWorkName2, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName2)))
c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network"))
}
func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectAlias(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
dockerCmd(c, "network", "create", "-d", "bridge", "net1")
dockerCmd(c, "network", "create", "-d", "bridge", "net2")
dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top")
c.Assert(waitRun("second"), check.IsNil)
// ping first container and its alias
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
c.Assert(err, check.IsNil)
// connect first container to net2 network
dockerCmd(c, "network", "connect", "--alias=bar", "net2", "first")
// connect second container to foo2 network with a different alias for first container
dockerCmd(c, "network", "connect", "net2", "second")
// ping the new alias in network foo2
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
c.Assert(err, check.IsNil)
// disconnect first container from net1 network
dockerCmd(c, "network", "disconnect", "net1", "first")
// ping to net1 scoped alias "foo" must fail
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
c.Assert(err, check.NotNil)
// ping to net2 scoped alias "bar" must still succeed
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
c.Assert(err, check.IsNil)
}

View file

@ -273,6 +273,37 @@ func (s *DockerSuite) TestUserDefinedNetworkLinksWithRestart(c *check.C) {
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestUserDefinedNetworkAlias(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
dockerCmd(c, "network", "create", "-d", "bridge", "net1")
dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo1", "--net-alias=foo2", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top")
c.Assert(waitRun("second"), check.IsNil)
// ping to first and its network-scoped aliases
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo1")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo2")
c.Assert(err, check.IsNil)
// Restart first container
dockerCmd(c, "restart", "first")
c.Assert(waitRun("first"), check.IsNil)
// ping to first and its network-scoped aliases must succeed
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo1")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo2")
c.Assert(err, check.IsNil)
}
// Issue 9677.
func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true")

View file

@ -52,6 +52,7 @@ docker-create - Create a new container
[**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
[**--name**[=*NAME*]]
[**--net**[=*"bridge"*]]
[**--net-alias**[=*[]*]]
[**--oom-kill-disable**]
[**--oom-score-adj**[=*0*]]
[**-P**|**--publish-all**]
@ -265,6 +266,9 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
'host': use the Docker host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
'<network-name>|<network-id>': connect to a user-defined network
**--net-alias**=[]
Add network-scoped alias for the container
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.

View file

@ -54,6 +54,7 @@ docker-run - Run a command in a new container
[**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
[**--name**[=*NAME*]]
[**--net**[=*"bridge"*]]
[**--net-alias**[=*[]*]]
[**--oom-kill-disable**]
[**--oom-score-adj**[=*0*]]
[**-P**|**--publish-all**]
@ -383,6 +384,9 @@ and foreground Docker containers.
'host': use the Docker host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
'<network-name>|<network-id>': connect to a user-defined network
**--net-alias**=[]
Add network-scoped alias for the container
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.

View file

@ -33,4 +33,6 @@ var (
ErrUnsupportedNetworkAndIP = fmt.Errorf("User specified IP address is supported on user defined networks only")
// ErrUnsupportedNetworkNoSubnetAndIP conflict between network with no configured subnet and preferred ip address
ErrUnsupportedNetworkNoSubnetAndIP = fmt.Errorf("User specified IP address is supported only when connecting to networks with user configured subnets")
// ErrUnsupportedNetworkAndAlias conflict between network mode and alias
ErrUnsupportedNetworkAndAlias = fmt.Errorf("Network-scoped alias is supported only for containers in user defined networks")
)

View file

@ -33,6 +33,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
flDeviceReadBps = NewThrottledeviceOpt(ValidateThrottleBpsDevice)
flDeviceWriteBps = NewThrottledeviceOpt(ValidateThrottleBpsDevice)
flLinks = opts.NewListOpts(ValidateLink)
flAliases = opts.NewListOpts(nil)
flDeviceReadIOps = NewThrottledeviceOpt(ValidateThrottleIOpsDevice)
flDeviceWriteIOps = NewThrottledeviceOpt(ValidateThrottleIOpsDevice)
flEnv = opts.NewListOpts(ValidateEnv)
@ -103,6 +104,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume")
cmd.Var(&flTmpfs, []string{"-tmpfs"}, "Mount a tmpfs directory")
cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
cmd.Var(&flAliases, []string{"-net-alias"}, "Add network-scoped alias for the container")
cmd.Var(&flDevices, []string{"-device"}, "Add a host device to the container")
cmd.Var(&flLabels, []string{"l", "-label"}, "Set meta data on a container")
cmd.Var(&flLabelsFile, []string{"-label-file"}, "Read in a line delimited file of labels")
@ -440,6 +442,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
}
if hostConfig.NetworkMode.IsUserDefined() && flAliases.Len() > 0 {
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
if epConfig == nil {
epConfig = &networktypes.EndpointSettings{}
}
epConfig.Aliases = make([]string, flAliases.Len())
copy(epConfig.Aliases, flAliases.GetAll())
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
}
return config, hostConfig, networkingConfig, cmd, nil
}