Merge pull request #19229 from mavenugo/udlinks

Local alias support
This commit is contained in:
Sebastiaan van Stijn 2016-01-12 16:47:32 -08:00
commit 47d87d3b92
12 changed files with 364 additions and 25 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/stringid"
runconfigopts "github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/network" "github.com/docker/engine-api/types/network"
@ -112,6 +113,8 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false) cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false)
flIPAddress := cmd.String([]string{"-ip"}, "", "IP Address") flIPAddress := cmd.String([]string{"-ip"}, "", "IP Address")
flIPv6Address := cmd.String([]string{"-ip6"}, "", "IPv6 Address") flIPv6Address := cmd.String([]string{"-ip6"}, "", "IPv6 Address")
flLinks := opts.NewListOpts(runconfigopts.ValidateLink)
cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
cmd.Require(flag.Min, 2) cmd.Require(flag.Min, 2)
if err := cmd.ParseFlags(args, true); err != nil { if err := cmd.ParseFlags(args, true); err != nil {
return err return err
@ -121,6 +124,7 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
IPv4Address: *flIPAddress, IPv4Address: *flIPAddress,
IPv6Address: *flIPv6Address, IPv6Address: *flIPv6Address,
}, },
Links: flLinks.GetAll(),
} }
return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig) return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig)
} }

View File

@ -18,6 +18,7 @@ import (
"github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/symlink" "github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
runconfigopts "github.com/docker/docker/runconfig/opts"
"github.com/docker/docker/utils" "github.com/docker/docker/utils"
"github.com/docker/docker/volume" "github.com/docker/docker/volume"
"github.com/docker/engine-api/types/container" "github.com/docker/engine-api/types/container"
@ -247,6 +248,21 @@ func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox)
return nil return nil
} }
// BuildJoinOptions builds endpoint Join options from a given network.
func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
var joinOptions []libnetwork.EndpointOption
if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok {
for _, str := range epConfig.Links {
name, alias, err := runconfigopts.ParseLink(str)
if err != nil {
return nil, err
}
joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
}
}
return joinOptions, nil
}
// BuildCreateEndpointOptions builds endpoint options from a given network. // BuildCreateEndpointOptions builds endpoint options from a given network.
func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) { func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
var ( var (

View File

@ -586,7 +586,7 @@ func (daemon *Daemon) updateContainerNetworkSettings(container *container.Contai
if container.NetworkSettings == nil { if container.NetworkSettings == nil {
container.NetworkSettings = &network.Settings{} container.NetworkSettings = &network.Settings{}
} }
if endpointsConfig != nil { if len(endpointsConfig) > 0 {
container.NetworkSettings.Networks = endpointsConfig container.NetworkSettings.Networks = endpointsConfig
} }
if container.NetworkSettings.Networks == nil { if container.NetworkSettings.Networks == nil {
@ -816,7 +816,12 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
container.UpdateSandboxNetworkSettings(sb) container.UpdateSandboxNetworkSettings(sb)
} }
if err := ep.Join(sb); err != nil { joinOptions, err := container.BuildJoinOptions(n)
if err != nil {
return err
}
if err := ep.Join(sb, joinOptions...); err != nil {
return err return err
} }

View File

@ -868,7 +868,7 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error
// registerLinks writes the links to a file. // registerLinks writes the links to a file.
func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
if hostConfig == nil { if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
return nil return nil
} }

View File

@ -15,6 +15,9 @@ parent = "smn_cli"
Connects a container to a network Connects a container to a network
--help Print usage --help Print usage
--ip IP Address
--ip6 IPv6 Address
--link=[] Add a link to another container
Connects a container to a network. You can connect a container by name Connects a container to a network. You can connect a container by name
or by ID. Once connected, the container can communicate with other containers in or by ID. Once connected, the container can communicate with other containers in
@ -33,7 +36,13 @@ $ docker run -itd --net=multi-host-network busybox
You can specify the IP address you want to be assigned to the container's interface. You can specify the IP address you want to be assigned to the container's interface.
```bash ```bash
$ docker network connect multi-host-network --ip 10.10.36.122 container2 $ docker network connect --ip 10.10.36.122 multi-host-network container2
```
You can use `--link` option to link another container with a prefered alias
```bash
$ docker network connect --link container1:c1 multi-host-network container2
``` ```
You can pause, restart, and stop containers that are connected to a network. You can pause, restart, and stop containers that are connected to a network.
@ -60,3 +69,4 @@ You can connect a container to one or more networks. The networks need not be th
* [network ls](network_ls.md) * [network ls](network_ls.md)
* [network rm](network_rm.md) * [network rm](network_rm.md)
* [Understand Docker container networks](../../userguide/networking/dockernetworks.md) * [Understand Docker container networks](../../userguide/networking/dockernetworks.md)
* [Work with networks](../../userguide/networking/work-with-networks.md)

View File

@ -1301,12 +1301,12 @@ specifies `EXPOSE 80` in the Dockerfile). At runtime, the port might be
bound to 42800 on the host. To find the mapping between the host ports bound to 42800 on the host. To find the mapping between the host ports
and the exposed ports, use `docker port`. and the exposed ports, use `docker port`.
If the operator uses `--link` when starting a new client container, then the If the operator uses `--link` when starting a new client container in the
client container can access the exposed port via a private networking interface. default bridge network, then the client container can access the exposed
Linking is a legacy feature that is only supported on the default bridge port via a private networking interface.
network. You should prefer the Docker networks feature instead. For more If `--link` is used when starting a container in a user-defined network as
information on this feature, see the [*Docker network described in [*Docker network overview*""](../userguide/networking/index.md)),
overview*""](../userguide/networking/index.md)). it will provide a named alias for the container being linked to.
### ENV (environment variables) ### ENV (environment variables)

View File

@ -17,14 +17,11 @@ Before the [Docker networks feature](../dockernetworks.md), you could use the
Docker link feature to allow containers to discover each other and securely Docker link feature to allow containers to discover each other and securely
transfer information about one container to another container. With the transfer information about one container to another container. With the
introduction of the Docker networks feature, you can still create links but they introduction of the Docker networks feature, you can still create links but they
are only supported on the default `bridge` network named `bridge` and appearing behave differently between default `bridge` network and
in your network stack as `docker0`. [user defined networks](../work-with-networks.md#linking-containers-in-user-defined-networks)
This section briefly discusses connecting via a network port and then goes into This section briefly discusses connecting via a network port and then goes into
detail on container linking. While links are still supported on Docker's default detail on container linking in default `bridge` network.
network (`bridge`), you should avoid them in preference of the Docker
networks feature. Linking is expected to be deprecated and removed in a future
release.
## Connect using network port mapping ## Connect using network port mapping

View File

@ -268,7 +268,7 @@ PING container3 (172.25.3.3): 56 data bytes
round-trip min/avg/max = 0.070/0.081/0.097 ms round-trip min/avg/max = 0.070/0.081/0.097 ms
``` ```
This isn't the case for the default bridge network. Both `container2` and `container1` are connected to the default bridge network. Docker does not support automatic service discovery on this network. For this reason, pinging `container1` by name fails as you would expect based on the `/etc/hosts` file: This isn't the case for the default `bridge` network. Both `container2` and `container1` are connected to the default bridge network. Docker does not support automatic service discovery on this network. For this reason, pinging `container1` by name fails as you would expect based on the `/etc/hosts` file:
```bash ```bash
/ # ping -w 4 container1 / # ping -w 4 container1
@ -314,6 +314,192 @@ PING 172.17.0.2 (172.17.0.2): 56 data bytes
You can connect both running and non-running containers to a network. However, You can connect both running and non-running containers to a network. However,
`docker network inspect` only displays information on running containers. `docker network inspect` only displays information on running containers.
### Linking containers in user-defined networks
In the above example, container_2 was able to resolve container_3's name automatically
in the user defined network `isolated_nw`, but the name resolution did not succeed
automatically in the default `bridge` network. This is expected in order to maintain
backward compatibility with [legacy link](default_network/dockerlinks.md).
The `legacy link` provided 4 major functionalities to the default `bridge` network.
* name resolution
* name alias for the linked container using `--link=CONTAINER-NAME:ALIAS`
* secured container connectivity (in isolation via `--icc=false`)
* environment variable injection
Comparing the above 4 functionalities with the non-default user-defined networks such as
`isolated_nw` in this example, without any additional config, `docker network` provides
* automatic name resolution using DNS
* automatic secured isolated environment for the containers in a network
* ability to dynamically attach and detach to multiple networks
* supports the `--link` option to provide name alias for the linked container
Continuing with the above example, create another container `container_4` in `isolated_nw`
with `--link` to provide additional name resolution using alias for other containers in
the same network.
```bash
$ docker run --net=isolated_nw -itd --name=container4 --link container5:c5 busybox
01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c
```
With the help of `--link` container4 will be able to reach container5 using the
aliased name `c5` as well.
Please note that while creating container4, we linked to a container named `container5`
which is not created yet. That is one of the differences in behavior between the
`legacy link` in default `bridge` network and the new `link` functionality in user defined
networks. The `legacy link` is static in nature and it hard-binds the container with the
alias and it doesnt tolerate linked container restarts. While the new `link` functionality
in user defined networks are dynamic in nature and supports linked container restarts
including tolerating ip-address changes on the linked container.
Now let us launch another container named `container5` linking container4 to c4.
```bash
$ docker run --net=isolated_nw -itd --name=container5 --link container4:c4 busybox
72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a
```
As expected, container4 will be able to reach container5 by both its container name and
its alias c5 and container5 will be able to reach container4 by its container name and
its alias c4.
```bash
$ docker attach container4
/ # ping -w 4 c5
PING c5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- c5 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 container5
PING container5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- container5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
```
```bash
$ docker attach container5
/ # ping -w 4 c4
PING c4 (172.25.0.4): 56 data bytes
64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms
64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms
64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms
64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms
--- c4 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.070/0.082 ms
/ # ping -w 4 container4
PING container4 (172.25.0.4): 56 data bytes
64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms
64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms
64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms
64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms
--- container4 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.070/0.082 ms
```
Similar to the legacy link functionality the new link alias is localized to a container
and the aliased name has no meaning outside of the container using the `--link`.
Also, it is important to note that if a container belongs to multiple networks, the
linked alias is scoped within a given network. Hence the containers can be linked to
different aliases in different networks.
Extending the example, let us create another network named `local_alias`
```bash
$ docker network create -d bridge --subnet 172.26.0.0/24 local_alias
76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa
```
let us connect container4 and container5 to the new network `local_alias`
```
$ docker network connect --link container5:foo local_alias container4
$ docker network connect --link container4:bar local_alias container5
```
```bash
$ docker attach container4
/ # ping -w 4 foo
PING foo (172.26.0.3): 56 data bytes
64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: 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
/ # ping -w 4 c5
PING c5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- c5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
```
Note that the ping succeeds for both the aliases but on different networks.
Let us conclude this section by disconnecting container5 from the `isolated_nw`
and observe the results
```
$ docker network disconnect isolated_nw container5
$ docker attach container4
/ # ping -w 4 c5
ping: bad address 'c5'
/ # ping -w 4 foo
PING foo (172.26.0.3): 56 data bytes
64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: 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
```
In conclusion, the new link functionality in user defined networks provides all the
benefits of legacy links while avoiding most of the well-known issues with `legacy links`.
One notable missing functionality compared to `legacy links` is the injection of
environment variables. Though very useful, environment variable injection is static
in nature and must be injected when the container is started. One cannot inject
environment variables into a running container without significant effort and hence
it is not compatible with `docker network` which provides a dynamic way to connect/
disconnect containers to/from a network.
## Disconnecting containers ## Disconnecting containers
You can disconnect a container from a network using the `docker network You can disconnect a container from a network using the `docker network

View File

@ -1040,3 +1040,44 @@ func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
out, _ = dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.GlobalIPv6Address }}'", nwname), cName) out, _ = dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.GlobalIPv6Address }}'", nwname), cName)
c.Assert(strings.TrimSpace(out), check.Equals, ipv6) c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
} }
func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
dockerCmd(c, "network", "create", "-d", "bridge", "foo2")
dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
// run a container in user-defined network udlinkNet with a link for an existing container
// and a link for a container that doesnt exist
dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1",
"--link=third:bar", "busybox", "top")
c.Assert(waitRun("second"), check.IsNil)
// ping to first and its alias FirstInFoo1 must succeed
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
c.Assert(err, check.IsNil)
// connect first container to foo2 network
dockerCmd(c, "network", "connect", "foo2", "first")
// connect second container to foo2 network with a different alias for first container
dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second")
// ping the new alias in network foo2
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
c.Assert(err, check.IsNil)
// disconnect first container from foo1 network
dockerCmd(c, "network", "disconnect", "foo1", "first")
// link in foo1 network must fail
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
c.Assert(err, check.NotNil)
// link in foo2 network must succeed
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
c.Assert(err, check.IsNil)
}

View File

@ -199,6 +199,80 @@ func (s *DockerSuite) TestRunLinksContainerWithContainerId(c *check.C) {
} }
} }
func (s *DockerSuite) TestUserDefinedNetworkLinks(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
// run a container in user-defined network udlinkNet with a link for an existing container
// and a link for a container that doesnt exist
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
"--link=third:bar", "busybox", "top")
c.Assert(waitRun("second"), check.IsNil)
// ping to first and its alias foo must succeed
_, _, 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)
// ping to third and its alias must fail
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
c.Assert(err, check.NotNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
c.Assert(err, check.NotNil)
// start third container now
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=third", "busybox", "top")
c.Assert(waitRun("third"), check.IsNil)
// ping to third and its alias must succeed now
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
c.Assert(err, check.IsNil)
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestUserDefinedNetworkLinksWithRestart(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
"busybox", "top")
c.Assert(waitRun("second"), check.IsNil)
// ping to first and its alias foo must succeed
_, _, 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)
// Restart first container
dockerCmd(c, "restart", "first")
c.Assert(waitRun("first"), check.IsNil)
// ping to first and its alias foo must still succeed
_, _, 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)
// Restart second container
dockerCmd(c, "restart", "second")
c.Assert(waitRun("second"), check.IsNil)
// ping to first and its alias foo must still succeed
_, _, 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)
}
// Issue 9677. // Issue 9677.
func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) { func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true") out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true")

View File

@ -48,10 +48,6 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
return ErrConflictContainerNetworkAndLinks return ErrConflictContainerNetworkAndLinks
} }
if hc.NetworkMode.IsUserDefined() && len(hc.Links) > 0 {
return ErrConflictUserDefinedNetworkAndLinks
}
if (hc.NetworkMode.IsHost() || hc.NetworkMode.IsContainer()) && len(hc.DNS) > 0 { if (hc.NetworkMode.IsHost() || hc.NetworkMode.IsContainer()) && len(hc.DNS) > 0 {
return ErrConflictNetworkAndDNS return ErrConflictNetworkAndDNS
} }

View File

@ -417,11 +417,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
config.StdinOnce = true config.StdinOnce = true
} }
var networkingConfig *networktypes.NetworkingConfig networkingConfig := &networktypes.NetworkingConfig{
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
}
if *flIPv4Address != "" || *flIPv6Address != "" { if *flIPv4Address != "" || *flIPv6Address != "" {
networkingConfig = &networktypes.NetworkingConfig{
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
}
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{ networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
IPAMConfig: &networktypes.EndpointIPAMConfig{ IPAMConfig: &networktypes.EndpointIPAMConfig{
IPv4Address: *flIPv4Address, IPv4Address: *flIPv4Address,
@ -430,6 +430,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
} }
} }
if hostConfig.NetworkMode.IsUserDefined() && len(hostConfig.Links) > 0 {
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
if epConfig == nil {
epConfig = &networktypes.EndpointSettings{}
}
epConfig.Links = make([]string, len(hostConfig.Links))
copy(epConfig.Links, hostConfig.Links)
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
}
return config, hostConfig, networkingConfig, cmd, nil return config, hostConfig, networkingConfig, cmd, nil
} }