فهرست منبع

Merge pull request #23415 from aboch/ll

Allow user to specify container's link-local addresses
Michael Crosby 9 سال پیش
والد
کامیت
c97fdbe3c5

+ 11 - 8
api/client/network/connect.go

@@ -12,12 +12,13 @@ import (
 )
 )
 
 
 type connectOptions struct {
 type connectOptions struct {
-	network     string
-	container   string
-	ipaddress   string
-	ipv6address string
-	links       opts.ListOpts
-	aliases     []string
+	network      string
+	container    string
+	ipaddress    string
+	ipv6address  string
+	links        opts.ListOpts
+	aliases      []string
+	linklocalips []string
 }
 }
 
 
 func newConnectCommand(dockerCli *client.DockerCli) *cobra.Command {
 func newConnectCommand(dockerCli *client.DockerCli) *cobra.Command {
@@ -41,6 +42,7 @@ func newConnectCommand(dockerCli *client.DockerCli) *cobra.Command {
 	flags.StringVar(&opts.ipv6address, "ip6", "", "IPv6 Address")
 	flags.StringVar(&opts.ipv6address, "ip6", "", "IPv6 Address")
 	flags.Var(&opts.links, "link", "Add link to another container")
 	flags.Var(&opts.links, "link", "Add link to another container")
 	flags.StringSliceVar(&opts.aliases, "alias", []string{}, "Add network-scoped alias for the container")
 	flags.StringSliceVar(&opts.aliases, "alias", []string{}, "Add network-scoped alias for the container")
+	flags.StringSliceVar(&opts.linklocalips, "link-local-ip", []string{}, "Add a link-local address for the container")
 
 
 	return cmd
 	return cmd
 }
 }
@@ -50,8 +52,9 @@ func runConnect(dockerCli *client.DockerCli, opts connectOptions) error {
 
 
 	epConfig := &network.EndpointSettings{
 	epConfig := &network.EndpointSettings{
 		IPAMConfig: &network.EndpointIPAMConfig{
 		IPAMConfig: &network.EndpointIPAMConfig{
-			IPv4Address: opts.ipaddress,
-			IPv6Address: opts.ipv6address,
+			IPv4Address:  opts.ipaddress,
+			IPv6Address:  opts.ipv6address,
+			LinkLocalIPs: opts.linklocalips,
 		},
 		},
 		Links:   opts.links.GetAll(),
 		Links:   opts.links.GetAll(),
 		Aliases: opts.aliases,
 		Aliases: opts.aliases,

+ 8 - 2
container/container.go

@@ -789,9 +789,15 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
 
 
 	if epConfig != nil {
 	if epConfig != nil {
 		ipam := epConfig.IPAMConfig
 		ipam := epConfig.IPAMConfig
-		if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "") {
+		if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "" || len(ipam.LinkLocalIPs) > 0) {
+			var ipList []net.IP
+			for _, ips := range ipam.LinkLocalIPs {
+				if ip := net.ParseIP(ips); ip != nil {
+					ipList = append(ipList, ip)
+				}
+			}
 			createOptions = append(createOptions,
 			createOptions = append(createOptions,
-				libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), nil, nil))
+				libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), ipList, nil))
 		}
 		}
 
 
 		for _, alias := range epConfig.Aliases {
 		for _, alias := range epConfig.Aliases {

+ 2 - 1
docs/reference/api/docker_remote_api_v1.24.md

@@ -339,7 +339,8 @@ Create a container
               "isolated_nw" : {
               "isolated_nw" : {
                   "IPAMConfig": {
                   "IPAMConfig": {
                       "IPv4Address":"172.20.30.33",
                       "IPv4Address":"172.20.30.33",
-                      "IPv6Address":"2001:db8:abcd::3033"
+                      "IPv6Address":"2001:db8:abcd::3033",
+                      "LinkLocalIPs:["169.254.34.68", "fe80::3468"]
                   },
                   },
                   "Links":["container_1", "container_2"],
                   "Links":["container_1", "container_2"],
                   "Aliases":["server_x", "server_y"]
                   "Aliases":["server_x", "server_y"]

+ 1 - 0
docs/reference/commandline/create.md

@@ -54,6 +54,7 @@ Creates a new container.
       -l, --label=[]                Set metadata on the container (e.g., --label=com.example.key=value)
       -l, --label=[]                Set metadata on the container (e.g., --label=com.example.key=value)
       --label-file=[]               Read in a line delimited file of labels
       --label-file=[]               Read in a line delimited file of labels
       --link=[]                     Add link to another container
       --link=[]                     Add link to another container
+      --link-local-ip=[]            Container IPv4/IPv6 link-local addresses (e.g. 169.254.0.77, fe80::77)
       --log-driver=""               Logging driver for container
       --log-driver=""               Logging driver for container
       --log-opt=[]                  Log driver specific options
       --log-opt=[]                  Log driver specific options
       -m, --memory=""               Memory limit
       -m, --memory=""               Memory limit

+ 1 - 0
docs/reference/commandline/network_connect.md

@@ -19,6 +19,7 @@ parent = "smn_cli"
       --ip               IPv4 Address
       --ip               IPv4 Address
       --ip6              IPv6 Address
       --ip6              IPv6 Address
       --link=[]          Add a link to another container
       --link=[]          Add a link to another container
+      --link-local-ip=[] IPv4/IPv6 link-local addresses
 
 
 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

+ 1 - 0
docs/reference/commandline/run.md

@@ -55,6 +55,7 @@ parent = "smn_cli"
       -l, --label=[]                Set metadata on the container (e.g., --label=com.example.key=value)
       -l, --label=[]                Set metadata on the container (e.g., --label=com.example.key=value)
       --label-file=[]               Read in a file of labels (EOL delimited)
       --label-file=[]               Read in a file of labels (EOL delimited)
       --link=[]                     Add link to another container
       --link=[]                     Add link to another container
+      --link-local-ip=[]            Container IPv4/IPv6 link-local addresses (e.g. 169.254.0.77, fe80::77)
       --log-driver=""               Logging driver for container
       --log-driver=""               Logging driver for container
       --log-opt=[]                  Log driver specific options
       --log-opt=[]                  Log driver specific options
       -m, --memory=""               Memory limit
       -m, --memory=""               Memory limit

+ 13 - 12
docs/reference/run.md

@@ -288,18 +288,19 @@ of the containers.
 
 
 ## Network settings
 ## Network settings
 
 
-    --dns=[]         : Set custom dns servers for the container
-    --net="bridge"   : Connect a container to a network
-                        'bridge': create a network stack on the default Docker bridge
-                        'none': no networking
-                        '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
-    --ip6=""         : Sets the container's Ethernet device's IPv6 address
+    --dns=[]           : Set custom dns servers for the container
+    --net="bridge"     : Connect a container to a network
+                          'bridge': create a network stack on the default Docker bridge
+                          'none': no networking
+                          '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
+    --ip6=""           : Sets the container's Ethernet device's IPv6 address
+    --link-local-ip=[] : Sets one or more container's Ethernet device's link local IPv4/IPv6 addresses
 
 
 By default, all containers have networking enabled and they can make any
 By default, all containers have networking enabled and they can make any
 outgoing connections. The operator can completely disable networking
 outgoing connections. The operator can completely disable networking

+ 47 - 0
integration-cli/docker_cli_network_unix_test.go

@@ -1336,6 +1336,53 @@ func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
 	c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
 	c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
 }
 }
 
 
+func (s *DockerNetworkSuite) TestDockerNetworkConnectLinkLocalIP(c *check.C) {
+	// create one test network
+	dockerCmd(c, "network", "create", "n0")
+	assertNwIsAvailable(c, "n0")
+
+	// run a container with incorrect link-local address
+	_, _, err := dockerCmdWithError("run", "--link-local-ip", "169.253.5.5", "busybox", "top")
+	c.Assert(err, check.NotNil)
+	_, _, err = dockerCmdWithError("run", "--link-local-ip", "2001:db8::89", "busybox", "top")
+	c.Assert(err, check.NotNil)
+
+	// run two containers with link-local ip on the test network
+	dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--link-local-ip", "169.254.7.7", "--link-local-ip", "fe80::254:77", "busybox", "top")
+	c.Assert(waitRun("c0"), check.IsNil)
+	dockerCmd(c, "run", "-d", "--name", "c1", "--net=n0", "--link-local-ip", "169.254.8.8", "--link-local-ip", "fe80::254:88", "busybox", "top")
+	c.Assert(waitRun("c1"), check.IsNil)
+
+	// run a container on the default network and connect it to the test network specifying a link-local address
+	dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top")
+	c.Assert(waitRun("c2"), check.IsNil)
+	dockerCmd(c, "network", "connect", "--link-local-ip", "169.254.9.9", "n0", "c2")
+
+	// verify the three containers can ping each other via the link-local addresses
+	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
+	c.Assert(err, check.IsNil)
+	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
+	c.Assert(err, check.IsNil)
+	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
+	c.Assert(err, check.IsNil)
+
+	// Stop and restart the three containers
+	dockerCmd(c, "stop", "c0")
+	dockerCmd(c, "stop", "c1")
+	dockerCmd(c, "stop", "c2")
+	dockerCmd(c, "start", "c0")
+	dockerCmd(c, "start", "c1")
+	dockerCmd(c, "start", "c2")
+
+	// verify the ping again
+	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
+	c.Assert(err, check.IsNil)
+	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
+	c.Assert(err, check.IsNil)
+	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
+	c.Assert(err, check.IsNil)
+}
+
 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
 	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
 	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
 	dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
 	dockerCmd(c, "network", "create", "-d", "bridge", "foo1")

+ 4 - 0
man/docker-create.1.md

@@ -43,6 +43,7 @@ docker-create - Create a new container
 [**-l**|**--label**[=*[]*]]
 [**-l**|**--label**[=*[]*]]
 [**--label-file**[=*[]*]]
 [**--label-file**[=*[]*]]
 [**--link**[=*[]*]]
 [**--link**[=*[]*]]
+[**--link-local-ip**[=*[]*]]
 [**--log-driver**[=*[]*]]
 [**--log-driver**[=*[]*]]
 [**--log-opt**[=*[]*]]
 [**--log-opt**[=*[]*]]
 [**-m**|**--memory**[=*MEMORY*]]
 [**-m**|**--memory**[=*MEMORY*]]
@@ -220,6 +221,9 @@ millions of trillions.
    Add link to another container in the form of <name or id>:alias or just
    Add link to another container in the form of <name or id>:alias or just
    <name or id> in which case the alias will match the name.
    <name or id> in which case the alias will match the name.
 
 
+**--link-local-ip**=[]
+   Add one or more link-local IPv4/IPv6 addresses to the container's interface
+
 **--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*etwlogs*|*gcplogs*|*none*"
 **--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*etwlogs*|*gcplogs*|*none*"
   Logging driver for container. Default is defined by daemon `--log-driver` flag.
   Logging driver for container. Default is defined by daemon `--log-driver` flag.
   **Warning**: the `docker logs` command works only for the `json-file` and
   **Warning**: the `docker logs` command works only for the `json-file` and

+ 4 - 0
man/docker-run.1.md

@@ -45,6 +45,7 @@ docker-run - Run a command in a new container
 [**-l**|**--label**[=*[]*]]
 [**-l**|**--label**[=*[]*]]
 [**--label-file**[=*[]*]]
 [**--label-file**[=*[]*]]
 [**--link**[=*[]*]]
 [**--link**[=*[]*]]
+[**--link-local-ip**[=*[]*]]
 [**--log-driver**[=*[]*]]
 [**--log-driver**[=*[]*]]
 [**--log-opt**[=*[]*]]
 [**--log-opt**[=*[]*]]
 [**-m**|**--memory**[=*MEMORY*]]
 [**-m**|**--memory**[=*MEMORY*]]
@@ -326,6 +327,9 @@ container can access the exposed port via a private networking interface. Docker
 will set some environment variables in the client container to help indicate
 will set some environment variables in the client container to help indicate
 which interface and port to use.
 which interface and port to use.
 
 
+**--link-local-ip**=[]
+   Add one or more link-local IPv4/IPv6 addresses to the container's interface
+
 **--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*etwlogs*|*gcplogs*|*none*"
 **--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*etwlogs*|*gcplogs*|*none*"
   Logging driver for container. Default is defined by daemon `--log-driver` flag.
   Logging driver for container. Default is defined by daemon `--log-driver` flag.
   **Warning**: the `docker logs` command works only for the `json-file` and
   **Warning**: the `docker logs` command works only for the `json-file` and

+ 15 - 6
runconfig/opts/parse.go

@@ -32,6 +32,7 @@ type ContainerOptions struct {
 	flDeviceWriteBps    ThrottledeviceOpt
 	flDeviceWriteBps    ThrottledeviceOpt
 	flLinks             opts.ListOpts
 	flLinks             opts.ListOpts
 	flAliases           opts.ListOpts
 	flAliases           opts.ListOpts
+	flLinkLocalIPs      opts.ListOpts
 	flDeviceReadIOps    ThrottledeviceOpt
 	flDeviceReadIOps    ThrottledeviceOpt
 	flDeviceWriteIOps   ThrottledeviceOpt
 	flDeviceWriteIOps   ThrottledeviceOpt
 	flEnv               opts.ListOpts
 	flEnv               opts.ListOpts
@@ -118,6 +119,7 @@ func AddFlags(flags *pflag.FlagSet) *ContainerOptions {
 		flDeviceWriteBps:    NewThrottledeviceOpt(ValidateThrottleBpsDevice),
 		flDeviceWriteBps:    NewThrottledeviceOpt(ValidateThrottleBpsDevice),
 		flLinks:             opts.NewListOpts(ValidateLink),
 		flLinks:             opts.NewListOpts(ValidateLink),
 		flAliases:           opts.NewListOpts(nil),
 		flAliases:           opts.NewListOpts(nil),
+		flLinkLocalIPs:      opts.NewListOpts(nil),
 		flDeviceReadIOps:    NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
 		flDeviceReadIOps:    NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
 		flDeviceWriteIOps:   NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
 		flDeviceWriteIOps:   NewThrottledeviceOpt(ValidateThrottleIOpsDevice),
 		flEnv:               opts.NewListOpts(ValidateEnv),
 		flEnv:               opts.NewListOpts(ValidateEnv),
@@ -203,6 +205,7 @@ func AddFlags(flags *pflag.FlagSet) *ContainerOptions {
 	flags.Var(&copts.flTmpfs, "tmpfs", "Mount a tmpfs directory")
 	flags.Var(&copts.flTmpfs, "tmpfs", "Mount a tmpfs directory")
 	flags.Var(&copts.flLinks, "link", "Add link to another container")
 	flags.Var(&copts.flLinks, "link", "Add link to another container")
 	flags.Var(&copts.flAliases, "net-alias", "Add network-scoped alias for the container")
 	flags.Var(&copts.flAliases, "net-alias", "Add network-scoped alias for the container")
+	flags.Var(&copts.flLinkLocalIPs, "link-local-ip", "Container IPv4/IPv6 link-local addresses")
 	flags.Var(&copts.flDevices, "device", "Add a host device to the container")
 	flags.Var(&copts.flDevices, "device", "Add a host device to the container")
 	flags.VarP(&copts.flLabels, "label", "l", "Set meta data on a container")
 	flags.VarP(&copts.flLabels, "label", "l", "Set meta data on a container")
 	flags.Var(&copts.flLabelsFile, "label-file", "Read in a line delimited file of labels")
 	flags.Var(&copts.flLabelsFile, "label-file", "Read in a line delimited file of labels")
@@ -577,12 +580,18 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c
 		EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
 		EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
 	}
 	}
 
 
-	if *copts.flIPv4Address != "" || *copts.flIPv6Address != "" {
-		networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
-			IPAMConfig: &networktypes.EndpointIPAMConfig{
-				IPv4Address: *copts.flIPv4Address,
-				IPv6Address: *copts.flIPv6Address,
-			},
+	if *copts.flIPv4Address != "" || *copts.flIPv6Address != "" || copts.flLinkLocalIPs.Len() > 0 {
+		epConfig := &networktypes.EndpointSettings{}
+		networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
+
+		epConfig.IPAMConfig = &networktypes.EndpointIPAMConfig{
+			IPv4Address: *copts.flIPv4Address,
+			IPv6Address: *copts.flIPv6Address,
+		}
+
+		if copts.flLinkLocalIPs.Len() > 0 {
+			epConfig.IPAMConfig.LinkLocalIPs = make([]string, copts.flLinkLocalIPs.Len())
+			copy(epConfig.IPAMConfig.LinkLocalIPs, copts.flLinkLocalIPs.GetAll())
 		}
 		}
 	}
 	}