| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/opts" |
| 11 | 11 |
flag "github.com/docker/docker/pkg/mflag" |
| 12 | 12 |
"github.com/docker/docker/pkg/stringid" |
| 13 |
+ runconfigopts "github.com/docker/docker/runconfig/opts" |
|
| 13 | 14 |
"github.com/docker/engine-api/types" |
| 14 | 15 |
"github.com/docker/engine-api/types/filters" |
| 15 | 16 |
"github.com/docker/engine-api/types/network" |
| ... | ... |
@@ -112,6 +113,8 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
| 112 | 112 |
cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false)
|
| 113 | 113 |
flIPAddress := cmd.String([]string{"-ip"}, "", "IP Address")
|
| 114 | 114 |
flIPv6Address := cmd.String([]string{"-ip6"}, "", "IPv6 Address")
|
| 115 |
+ flLinks := opts.NewListOpts(runconfigopts.ValidateLink) |
|
| 116 |
+ cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
|
|
| 115 | 117 |
cmd.Require(flag.Min, 2) |
| 116 | 118 |
if err := cmd.ParseFlags(args, true); err != nil {
|
| 117 | 119 |
return err |
| ... | ... |
@@ -121,6 +124,7 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
| 121 | 121 |
IPv4Address: *flIPAddress, |
| 122 | 122 |
IPv6Address: *flIPv6Address, |
| 123 | 123 |
}, |
| 124 |
+ Links: flLinks.GetAll(), |
|
| 124 | 125 |
} |
| 125 | 126 |
return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig) |
| 126 | 127 |
} |
| ... | ... |
@@ -18,6 +18,7 @@ import ( |
| 18 | 18 |
"github.com/docker/docker/pkg/chrootarchive" |
| 19 | 19 |
"github.com/docker/docker/pkg/symlink" |
| 20 | 20 |
"github.com/docker/docker/pkg/system" |
| 21 |
+ runconfigopts "github.com/docker/docker/runconfig/opts" |
|
| 21 | 22 |
"github.com/docker/docker/utils" |
| 22 | 23 |
"github.com/docker/docker/volume" |
| 23 | 24 |
"github.com/docker/engine-api/types/container" |
| ... | ... |
@@ -247,6 +248,21 @@ func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox) |
| 247 | 247 |
return nil |
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 |
+// BuildJoinOptions builds endpoint Join options from a given network. |
|
| 251 |
+func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
|
|
| 252 |
+ var joinOptions []libnetwork.EndpointOption |
|
| 253 |
+ if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok {
|
|
| 254 |
+ for _, str := range epConfig.Links {
|
|
| 255 |
+ name, alias, err := runconfigopts.ParseLink(str) |
|
| 256 |
+ if err != nil {
|
|
| 257 |
+ return nil, err |
|
| 258 |
+ } |
|
| 259 |
+ joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias)) |
|
| 260 |
+ } |
|
| 261 |
+ } |
|
| 262 |
+ return joinOptions, nil |
|
| 263 |
+} |
|
| 264 |
+ |
|
| 250 | 265 |
// BuildCreateEndpointOptions builds endpoint options from a given network. |
| 251 | 266 |
func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
|
| 252 | 267 |
var ( |
| ... | ... |
@@ -586,7 +586,7 @@ func (daemon *Daemon) updateContainerNetworkSettings(container *container.Contai |
| 586 | 586 |
if container.NetworkSettings == nil {
|
| 587 | 587 |
container.NetworkSettings = &network.Settings{}
|
| 588 | 588 |
} |
| 589 |
- if endpointsConfig != nil {
|
|
| 589 |
+ if len(endpointsConfig) > 0 {
|
|
| 590 | 590 |
container.NetworkSettings.Networks = endpointsConfig |
| 591 | 591 |
} |
| 592 | 592 |
if container.NetworkSettings.Networks == nil {
|
| ... | ... |
@@ -816,7 +816,12 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName |
| 816 | 816 |
container.UpdateSandboxNetworkSettings(sb) |
| 817 | 817 |
} |
| 818 | 818 |
|
| 819 |
- if err := ep.Join(sb); err != nil {
|
|
| 819 |
+ joinOptions, err := container.BuildJoinOptions(n) |
|
| 820 |
+ if err != nil {
|
|
| 821 |
+ return err |
|
| 822 |
+ } |
|
| 823 |
+ |
|
| 824 |
+ if err := ep.Join(sb, joinOptions...); err != nil {
|
|
| 820 | 825 |
return err |
| 821 | 826 |
} |
| 822 | 827 |
|
| ... | ... |
@@ -868,7 +868,7 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error |
| 868 | 868 |
|
| 869 | 869 |
// registerLinks writes the links to a file. |
| 870 | 870 |
func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
| 871 |
- if hostConfig == nil {
|
|
| 871 |
+ if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
|
|
| 872 | 872 |
return nil |
| 873 | 873 |
} |
| 874 | 874 |
|
| ... | ... |
@@ -15,6 +15,9 @@ parent = "smn_cli" |
| 15 | 15 |
Connects a container to a network |
| 16 | 16 |
|
| 17 | 17 |
--help Print usage |
| 18 |
+ --ip IP Address |
|
| 19 |
+ --ip6 IPv6 Address |
|
| 20 |
+ --link=[] Add a link to another container |
|
| 18 | 21 |
|
| 19 | 22 |
Connects a container to a network. You can connect a container by name |
| 20 | 23 |
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 |
| 33 | 33 |
You can specify the IP address you want to be assigned to the container's interface. |
| 34 | 34 |
|
| 35 | 35 |
```bash |
| 36 |
-$ docker network connect multi-host-network --ip 10.10.36.122 container2 |
|
| 36 |
+$ docker network connect --ip 10.10.36.122 multi-host-network container2 |
|
| 37 |
+``` |
|
| 38 |
+ |
|
| 39 |
+You can use `--link` option to link another container with a prefered alias |
|
| 40 |
+ |
|
| 41 |
+```bash |
|
| 42 |
+$ docker network connect --link container1:c1 multi-host-network container2 |
|
| 37 | 43 |
``` |
| 38 | 44 |
|
| 39 | 45 |
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 |
| 60 | 60 |
* [network ls](network_ls.md) |
| 61 | 61 |
* [network rm](network_rm.md) |
| 62 | 62 |
* [Understand Docker container networks](../../userguide/networking/dockernetworks.md) |
| 63 |
+* [Work with networks](../../userguide/networking/work-with-networks.md) |
| ... | ... |
@@ -1301,12 +1301,12 @@ specifies `EXPOSE 80` in the Dockerfile). At runtime, the port might be |
| 1301 | 1301 |
bound to 42800 on the host. To find the mapping between the host ports |
| 1302 | 1302 |
and the exposed ports, use `docker port`. |
| 1303 | 1303 |
|
| 1304 |
-If the operator uses `--link` when starting a new client container, then the |
|
| 1305 |
-client container can access the exposed port via a private networking interface. |
|
| 1306 |
-Linking is a legacy feature that is only supported on the default bridge |
|
| 1307 |
-network. You should prefer the Docker networks feature instead. For more |
|
| 1308 |
-information on this feature, see the [*Docker network |
|
| 1309 |
-overview*""](../userguide/networking/index.md)). |
|
| 1304 |
+If the operator uses `--link` when starting a new client container in the |
|
| 1305 |
+default bridge network, then the client container can access the exposed |
|
| 1306 |
+port via a private networking interface. |
|
| 1307 |
+If `--link` is used when starting a container in a user-defined network as |
|
| 1308 |
+described in [*Docker network overview*""](../userguide/networking/index.md)), |
|
| 1309 |
+it will provide a named alias for the container being linked to. |
|
| 1310 | 1310 |
|
| 1311 | 1311 |
### ENV (environment variables) |
| 1312 | 1312 |
|
| ... | ... |
@@ -17,14 +17,11 @@ Before the [Docker networks feature](../dockernetworks.md), you could use the |
| 17 | 17 |
Docker link feature to allow containers to discover each other and securely |
| 18 | 18 |
transfer information about one container to another container. With the |
| 19 | 19 |
introduction of the Docker networks feature, you can still create links but they |
| 20 |
-are only supported on the default `bridge` network named `bridge` and appearing |
|
| 21 |
-in your network stack as `docker0`. |
|
| 20 |
+behave differently between default `bridge` network and |
|
| 21 |
+[user defined networks](../work-with-networks.md#linking-containers-in-user-defined-networks) |
|
| 22 | 22 |
|
| 23 | 23 |
This section briefly discusses connecting via a network port and then goes into |
| 24 |
-detail on container linking. While links are still supported on Docker's default |
|
| 25 |
-network (`bridge`), you should avoid them in preference of the Docker |
|
| 26 |
-networks feature. Linking is expected to be deprecated and removed in a future |
|
| 27 |
-release. |
|
| 24 |
+detail on container linking in default `bridge` network. |
|
| 28 | 25 |
|
| 29 | 26 |
## Connect using network port mapping |
| 30 | 27 |
|
| ... | ... |
@@ -268,7 +268,7 @@ PING container3 (172.25.3.3): 56 data bytes |
| 268 | 268 |
round-trip min/avg/max = 0.070/0.081/0.097 ms |
| 269 | 269 |
``` |
| 270 | 270 |
|
| 271 |
-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: |
|
| 271 |
+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: |
|
| 272 | 272 |
|
| 273 | 273 |
```bash |
| 274 | 274 |
/ # ping -w 4 container1 |
| ... | ... |
@@ -314,6 +314,192 @@ PING 172.17.0.2 (172.17.0.2): 56 data bytes |
| 314 | 314 |
You can connect both running and non-running containers to a network. However, |
| 315 | 315 |
`docker network inspect` only displays information on running containers. |
| 316 | 316 |
|
| 317 |
+### Linking containers in user-defined networks |
|
| 318 |
+ |
|
| 319 |
+In the above example, container_2 was able to resolve container_3's name automatically |
|
| 320 |
+in the user defined network `isolated_nw`, but the name resolution did not succeed |
|
| 321 |
+automatically in the default `bridge` network. This is expected in order to maintain |
|
| 322 |
+backward compatibility with [legacy link](default_network/dockerlinks.md). |
|
| 323 |
+ |
|
| 324 |
+The `legacy link` provided 4 major functionalities to the default `bridge` network. |
|
| 325 |
+ |
|
| 326 |
+* name resolution |
|
| 327 |
+* name alias for the linked container using `--link=CONTAINER-NAME:ALIAS` |
|
| 328 |
+* secured container connectivity (in isolation via `--icc=false`) |
|
| 329 |
+* environment variable injection |
|
| 330 |
+ |
|
| 331 |
+Comparing the above 4 functionalities with the non-default user-defined networks such as |
|
| 332 |
+`isolated_nw` in this example, without any additional config, `docker network` provides |
|
| 333 |
+ |
|
| 334 |
+* automatic name resolution using DNS |
|
| 335 |
+* automatic secured isolated environment for the containers in a network |
|
| 336 |
+* ability to dynamically attach and detach to multiple networks |
|
| 337 |
+* supports the `--link` option to provide name alias for the linked container |
|
| 338 |
+ |
|
| 339 |
+Continuing with the above example, create another container `container_4` in `isolated_nw` |
|
| 340 |
+with `--link` to provide additional name resolution using alias for other containers in |
|
| 341 |
+the same network. |
|
| 342 |
+ |
|
| 343 |
+```bash |
|
| 344 |
+$ docker run --net=isolated_nw -itd --name=container4 --link container5:c5 busybox |
|
| 345 |
+01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c |
|
| 346 |
+``` |
|
| 347 |
+ |
|
| 348 |
+With the help of `--link` container4 will be able to reach container5 using the |
|
| 349 |
+aliased name `c5` as well. |
|
| 350 |
+ |
|
| 351 |
+Please note that while creating container4, we linked to a container named `container5` |
|
| 352 |
+which is not created yet. That is one of the differences in behavior between the |
|
| 353 |
+`legacy link` in default `bridge` network and the new `link` functionality in user defined |
|
| 354 |
+networks. The `legacy link` is static in nature and it hard-binds the container with the |
|
| 355 |
+alias and it doesnt tolerate linked container restarts. While the new `link` functionality |
|
| 356 |
+in user defined networks are dynamic in nature and supports linked container restarts |
|
| 357 |
+including tolerating ip-address changes on the linked container. |
|
| 358 |
+ |
|
| 359 |
+Now let us launch another container named `container5` linking container4 to c4. |
|
| 360 |
+ |
|
| 361 |
+```bash |
|
| 362 |
+$ docker run --net=isolated_nw -itd --name=container5 --link container4:c4 busybox |
|
| 363 |
+72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a |
|
| 364 |
+``` |
|
| 365 |
+ |
|
| 366 |
+As expected, container4 will be able to reach container5 by both its container name and |
|
| 367 |
+its alias c5 and container5 will be able to reach container4 by its container name and |
|
| 368 |
+its alias c4. |
|
| 369 |
+ |
|
| 370 |
+```bash |
|
| 371 |
+$ docker attach container4 |
|
| 372 |
+/ # ping -w 4 c5 |
|
| 373 |
+PING c5 (172.25.0.5): 56 data bytes |
|
| 374 |
+64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms |
|
| 375 |
+64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms |
|
| 376 |
+64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms |
|
| 377 |
+64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms |
|
| 378 |
+ |
|
| 379 |
+--- c5 ping statistics --- |
|
| 380 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 381 |
+round-trip min/avg/max = 0.070/0.081/0.097 ms |
|
| 382 |
+ |
|
| 383 |
+/ # ping -w 4 container5 |
|
| 384 |
+PING container5 (172.25.0.5): 56 data bytes |
|
| 385 |
+64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms |
|
| 386 |
+64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms |
|
| 387 |
+64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms |
|
| 388 |
+64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms |
|
| 389 |
+ |
|
| 390 |
+--- container5 ping statistics --- |
|
| 391 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 392 |
+round-trip min/avg/max = 0.070/0.081/0.097 ms |
|
| 393 |
+``` |
|
| 394 |
+ |
|
| 395 |
+```bash |
|
| 396 |
+$ docker attach container5 |
|
| 397 |
+/ # ping -w 4 c4 |
|
| 398 |
+PING c4 (172.25.0.4): 56 data bytes |
|
| 399 |
+64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms |
|
| 400 |
+64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms |
|
| 401 |
+64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms |
|
| 402 |
+64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms |
|
| 403 |
+ |
|
| 404 |
+--- c4 ping statistics --- |
|
| 405 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 406 |
+round-trip min/avg/max = 0.065/0.070/0.082 ms |
|
| 407 |
+ |
|
| 408 |
+/ # ping -w 4 container4 |
|
| 409 |
+PING container4 (172.25.0.4): 56 data bytes |
|
| 410 |
+64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms |
|
| 411 |
+64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms |
|
| 412 |
+64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms |
|
| 413 |
+64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms |
|
| 414 |
+ |
|
| 415 |
+--- container4 ping statistics --- |
|
| 416 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 417 |
+round-trip min/avg/max = 0.065/0.070/0.082 ms |
|
| 418 |
+``` |
|
| 419 |
+ |
|
| 420 |
+Similar to the legacy link functionality the new link alias is localized to a container |
|
| 421 |
+and the aliased name has no meaning outside of the container using the `--link`. |
|
| 422 |
+ |
|
| 423 |
+Also, it is important to note that if a container belongs to multiple networks, the |
|
| 424 |
+linked alias is scoped within a given network. Hence the containers can be linked to |
|
| 425 |
+different aliases in different networks. |
|
| 426 |
+ |
|
| 427 |
+Extending the example, let us create another network named `local_alias` |
|
| 428 |
+ |
|
| 429 |
+```bash |
|
| 430 |
+$ docker network create -d bridge --subnet 172.26.0.0/24 local_alias |
|
| 431 |
+76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa |
|
| 432 |
+``` |
|
| 433 |
+ |
|
| 434 |
+let us connect container4 and container5 to the new network `local_alias` |
|
| 435 |
+ |
|
| 436 |
+``` |
|
| 437 |
+$ docker network connect --link container5:foo local_alias container4 |
|
| 438 |
+$ docker network connect --link container4:bar local_alias container5 |
|
| 439 |
+``` |
|
| 440 |
+ |
|
| 441 |
+```bash |
|
| 442 |
+$ docker attach container4 |
|
| 443 |
+ |
|
| 444 |
+/ # ping -w 4 foo |
|
| 445 |
+PING foo (172.26.0.3): 56 data bytes |
|
| 446 |
+64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms |
|
| 447 |
+64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms |
|
| 448 |
+64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms |
|
| 449 |
+64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms |
|
| 450 |
+ |
|
| 451 |
+--- foo ping statistics --- |
|
| 452 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 453 |
+round-trip min/avg/max = 0.070/0.081/0.097 ms |
|
| 454 |
+ |
|
| 455 |
+/ # ping -w 4 c5 |
|
| 456 |
+PING c5 (172.25.0.5): 56 data bytes |
|
| 457 |
+64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms |
|
| 458 |
+64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms |
|
| 459 |
+64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms |
|
| 460 |
+64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms |
|
| 461 |
+ |
|
| 462 |
+--- c5 ping statistics --- |
|
| 463 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 464 |
+round-trip min/avg/max = 0.070/0.081/0.097 ms |
|
| 465 |
+``` |
|
| 466 |
+ |
|
| 467 |
+Note that the ping succeeds for both the aliases but on different networks. |
|
| 468 |
+Let us conclude this section by disconnecting container5 from the `isolated_nw` |
|
| 469 |
+and observe the results |
|
| 470 |
+ |
|
| 471 |
+``` |
|
| 472 |
+$ docker network disconnect isolated_nw container5 |
|
| 473 |
+ |
|
| 474 |
+$ docker attach container4 |
|
| 475 |
+ |
|
| 476 |
+/ # ping -w 4 c5 |
|
| 477 |
+ping: bad address 'c5' |
|
| 478 |
+ |
|
| 479 |
+/ # ping -w 4 foo |
|
| 480 |
+PING foo (172.26.0.3): 56 data bytes |
|
| 481 |
+64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms |
|
| 482 |
+64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms |
|
| 483 |
+64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms |
|
| 484 |
+64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms |
|
| 485 |
+ |
|
| 486 |
+--- foo ping statistics --- |
|
| 487 |
+4 packets transmitted, 4 packets received, 0% packet loss |
|
| 488 |
+round-trip min/avg/max = 0.070/0.081/0.097 ms |
|
| 489 |
+ |
|
| 490 |
+``` |
|
| 491 |
+ |
|
| 492 |
+In conclusion, the new link functionality in user defined networks provides all the |
|
| 493 |
+benefits of legacy links while avoiding most of the well-known issues with `legacy links`. |
|
| 494 |
+ |
|
| 495 |
+One notable missing functionality compared to `legacy links` is the injection of |
|
| 496 |
+environment variables. Though very useful, environment variable injection is static |
|
| 497 |
+in nature and must be injected when the container is started. One cannot inject |
|
| 498 |
+environment variables into a running container without significant effort and hence |
|
| 499 |
+it is not compatible with `docker network` which provides a dynamic way to connect/ |
|
| 500 |
+disconnect containers to/from a network. |
|
| 501 |
+ |
|
| 502 |
+ |
|
| 317 | 503 |
## Disconnecting containers |
| 318 | 504 |
|
| 319 | 505 |
You can disconnect a container from a network using the `docker network |
| ... | ... |
@@ -1040,3 +1040,44 @@ func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
|
| 1040 | 1040 |
out, _ = dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.GlobalIPv6Address }}'", nwname), cName)
|
| 1041 | 1041 |
c.Assert(strings.TrimSpace(out), check.Equals, ipv6) |
| 1042 | 1042 |
} |
| 1043 |
+ |
|
| 1044 |
+func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
|
|
| 1045 |
+ testRequires(c, DaemonIsLinux, NotUserNamespace) |
|
| 1046 |
+ dockerCmd(c, "network", "create", "-d", "bridge", "foo1") |
|
| 1047 |
+ dockerCmd(c, "network", "create", "-d", "bridge", "foo2") |
|
| 1048 |
+ |
|
| 1049 |
+ dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top") |
|
| 1050 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 1051 |
+ |
|
| 1052 |
+ // run a container in user-defined network udlinkNet with a link for an existing container |
|
| 1053 |
+ // and a link for a container that doesnt exist |
|
| 1054 |
+ dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1", |
|
| 1055 |
+ "--link=third:bar", "busybox", "top") |
|
| 1056 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 1057 |
+ |
|
| 1058 |
+ // ping to first and its alias FirstInFoo1 must succeed |
|
| 1059 |
+ _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
|
| 1060 |
+ c.Assert(err, check.IsNil) |
|
| 1061 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
|
|
| 1062 |
+ c.Assert(err, check.IsNil) |
|
| 1063 |
+ |
|
| 1064 |
+ // connect first container to foo2 network |
|
| 1065 |
+ dockerCmd(c, "network", "connect", "foo2", "first") |
|
| 1066 |
+ // connect second container to foo2 network with a different alias for first container |
|
| 1067 |
+ dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second") |
|
| 1068 |
+ |
|
| 1069 |
+ // ping the new alias in network foo2 |
|
| 1070 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
|
|
| 1071 |
+ c.Assert(err, check.IsNil) |
|
| 1072 |
+ |
|
| 1073 |
+ // disconnect first container from foo1 network |
|
| 1074 |
+ dockerCmd(c, "network", "disconnect", "foo1", "first") |
|
| 1075 |
+ |
|
| 1076 |
+ // link in foo1 network must fail |
|
| 1077 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
|
|
| 1078 |
+ c.Assert(err, check.NotNil) |
|
| 1079 |
+ |
|
| 1080 |
+ // link in foo2 network must succeed |
|
| 1081 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
|
|
| 1082 |
+ c.Assert(err, check.IsNil) |
|
| 1083 |
+} |
| ... | ... |
@@ -199,6 +199,80 @@ func (s *DockerSuite) TestRunLinksContainerWithContainerId(c *check.C) {
|
| 199 | 199 |
} |
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 |
+func (s *DockerSuite) TestUserDefinedNetworkLinks(c *check.C) {
|
|
| 203 |
+ testRequires(c, DaemonIsLinux, NotUserNamespace) |
|
| 204 |
+ dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet") |
|
| 205 |
+ |
|
| 206 |
+ dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top") |
|
| 207 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 208 |
+ |
|
| 209 |
+ // run a container in user-defined network udlinkNet with a link for an existing container |
|
| 210 |
+ // and a link for a container that doesnt exist |
|
| 211 |
+ dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo", |
|
| 212 |
+ "--link=third:bar", "busybox", "top") |
|
| 213 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 214 |
+ |
|
| 215 |
+ // ping to first and its alias foo must succeed |
|
| 216 |
+ _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
|
| 217 |
+ c.Assert(err, check.IsNil) |
|
| 218 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
|
| 219 |
+ c.Assert(err, check.IsNil) |
|
| 220 |
+ |
|
| 221 |
+ // ping to third and its alias must fail |
|
| 222 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
|
|
| 223 |
+ c.Assert(err, check.NotNil) |
|
| 224 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
|
|
| 225 |
+ c.Assert(err, check.NotNil) |
|
| 226 |
+ |
|
| 227 |
+ // start third container now |
|
| 228 |
+ dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=third", "busybox", "top") |
|
| 229 |
+ c.Assert(waitRun("third"), check.IsNil)
|
|
| 230 |
+ |
|
| 231 |
+ // ping to third and its alias must succeed now |
|
| 232 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
|
|
| 233 |
+ c.Assert(err, check.IsNil) |
|
| 234 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
|
|
| 235 |
+ c.Assert(err, check.IsNil) |
|
| 236 |
+} |
|
| 237 |
+ |
|
| 238 |
+func (s *DockerSuite) TestUserDefinedNetworkLinksWithRestart(c *check.C) {
|
|
| 239 |
+ testRequires(c, DaemonIsLinux, NotUserNamespace) |
|
| 240 |
+ dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet") |
|
| 241 |
+ |
|
| 242 |
+ dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top") |
|
| 243 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 244 |
+ |
|
| 245 |
+ dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo", |
|
| 246 |
+ "busybox", "top") |
|
| 247 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 248 |
+ |
|
| 249 |
+ // ping to first and its alias foo must succeed |
|
| 250 |
+ _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
|
| 251 |
+ c.Assert(err, check.IsNil) |
|
| 252 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
|
| 253 |
+ c.Assert(err, check.IsNil) |
|
| 254 |
+ |
|
| 255 |
+ // Restart first container |
|
| 256 |
+ dockerCmd(c, "restart", "first") |
|
| 257 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 258 |
+ |
|
| 259 |
+ // ping to first and its alias foo must still succeed |
|
| 260 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
|
| 261 |
+ c.Assert(err, check.IsNil) |
|
| 262 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
|
| 263 |
+ c.Assert(err, check.IsNil) |
|
| 264 |
+ |
|
| 265 |
+ // Restart second container |
|
| 266 |
+ dockerCmd(c, "restart", "second") |
|
| 267 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 268 |
+ |
|
| 269 |
+ // ping to first and its alias foo must still succeed |
|
| 270 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
|
| 271 |
+ c.Assert(err, check.IsNil) |
|
| 272 |
+ _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
|
| 273 |
+ c.Assert(err, check.IsNil) |
|
| 274 |
+} |
|
| 275 |
+ |
|
| 202 | 276 |
// Issue 9677. |
| 203 | 277 |
func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
|
| 204 | 278 |
out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true")
|
| ... | ... |
@@ -48,10 +48,6 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
|
| 48 | 48 |
return ErrConflictContainerNetworkAndLinks |
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
- if hc.NetworkMode.IsUserDefined() && len(hc.Links) > 0 {
|
|
| 52 |
- return ErrConflictUserDefinedNetworkAndLinks |
|
| 53 |
- } |
|
| 54 |
- |
|
| 55 | 51 |
if (hc.NetworkMode.IsHost() || hc.NetworkMode.IsContainer()) && len(hc.DNS) > 0 {
|
| 56 | 52 |
return ErrConflictNetworkAndDNS |
| 57 | 53 |
} |
| ... | ... |
@@ -417,11 +417,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host |
| 417 | 417 |
config.StdinOnce = true |
| 418 | 418 |
} |
| 419 | 419 |
|
| 420 |
- var networkingConfig *networktypes.NetworkingConfig |
|
| 420 |
+ networkingConfig := &networktypes.NetworkingConfig{
|
|
| 421 |
+ EndpointsConfig: make(map[string]*networktypes.EndpointSettings), |
|
| 422 |
+ } |
|
| 423 |
+ |
|
| 421 | 424 |
if *flIPv4Address != "" || *flIPv6Address != "" {
|
| 422 |
- networkingConfig = &networktypes.NetworkingConfig{
|
|
| 423 |
- EndpointsConfig: make(map[string]*networktypes.EndpointSettings), |
|
| 424 |
- } |
|
| 425 | 425 |
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
|
| 426 | 426 |
IPAMConfig: &networktypes.EndpointIPAMConfig{
|
| 427 | 427 |
IPv4Address: *flIPv4Address, |
| ... | ... |
@@ -430,6 +430,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host |
| 430 | 430 |
} |
| 431 | 431 |
} |
| 432 | 432 |
|
| 433 |
+ if hostConfig.NetworkMode.IsUserDefined() && len(hostConfig.Links) > 0 {
|
|
| 434 |
+ epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] |
|
| 435 |
+ if epConfig == nil {
|
|
| 436 |
+ epConfig = &networktypes.EndpointSettings{}
|
|
| 437 |
+ } |
|
| 438 |
+ epConfig.Links = make([]string, len(hostConfig.Links)) |
|
| 439 |
+ copy(epConfig.Links, hostConfig.Links) |
|
| 440 |
+ networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig |
|
| 441 |
+ } |
|
| 442 |
+ |
|
| 433 | 443 |
return config, hostConfig, networkingConfig, cmd, nil |
| 434 | 444 |
} |
| 435 | 445 |
|