From c0897a45146732176d171e568ea05f3ac550d7e4 Mon Sep 17 00:00:00 2001 From: Malte Janduda Date: Fri, 3 Oct 2014 23:02:17 +0200 Subject: [PATCH 1/3] Adding docker-cli run param to set MAC address Signed-off-by: Malte Janduda Upstream-commit: f2df38050e019c0db265e7c3e38ee0de8948ca77 Component: engine --- components/engine/daemon/container.go | 1 + components/engine/docs/man/docker-run.1.md | 9 +++++ .../docs/sources/articles/networking.md | 14 ++++++-- .../reference/api/docker_remote_api.md | 4 +++ .../reference/api/docker_remote_api_v1.15.md | 1 + .../reference/api/docker_remote_api_v1.16.md | 1 + .../docs/sources/reference/commandline/cli.md | 8 +++++ .../engine/docs/sources/reference/run.md | 19 ++++++---- .../integration-cli/docker_cli_run_test.go | 35 +++++++++++++++++++ components/engine/runconfig/config.go | 2 ++ components/engine/runconfig/parse.go | 2 ++ 11 files changed, 87 insertions(+), 9 deletions(-) diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go index a477f19f22..6a717c2c9e 100644 --- a/components/engine/daemon/container.go +++ b/components/engine/daemon/container.go @@ -457,6 +457,7 @@ func (container *Container) AllocateNetwork() error { ) job := eng.Job("allocate_interface", container.ID) + job.Setenv("RequestedMac", container.Config.MacAddress) if env, err = job.Stdout.AddEnv(); err != nil { return err } diff --git a/components/engine/docs/man/docker-run.1.md b/components/engine/docs/man/docker-run.1.md index 485965381c..ce2ffeb434 100644 --- a/components/engine/docs/man/docker-run.1.md +++ b/components/engine/docs/man/docker-run.1.md @@ -29,6 +29,7 @@ docker-run - Run a command in a new container [**-m**|**--memory**[=*MEMORY*]] [**--name**[=*NAME*]] [**--net**[=*"bridge"*]] +[**--mac-address**[=*MACADDRESS*]] [**-P**|**--publish-all**[=*false*]] [**-p**|**--publish**[=*[]*]] [**--privileged**[=*false*]] @@ -187,6 +188,14 @@ and foreground Docker containers. 'container:': reuses another container network stack 'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. +**--mac-address**=*macaddress* + Set the MAC address for the container's ethernet device: + --mac-address=12:34:56:78:9a:bc + +Remember that the MAC address in an ethernet network must be unique. +The IPv6 link-local address will be based on the device's MAC address +according to RFC4862. + **-P**, **--publish-all**=*true*|*false* When set to true publish all exposed ports to the host interfaces. The default is false. If the operator uses -P (or -p) then Docker will make the diff --git a/components/engine/docs/sources/articles/networking.md b/components/engine/docs/sources/articles/networking.md index 036babb006..49f3722216 100644 --- a/components/engine/docs/sources/articles/networking.md +++ b/components/engine/docs/sources/articles/networking.md @@ -104,6 +104,9 @@ Finally, several networking options can only be provided when calling * `--net=bridge|none|container:NAME_or_ID|host` — see [How Docker networks a container](#container-networking) + * `--mac-address=MACADDRESS...` — see + [How docker networks a container](#container-networking) + * `-p SPEC` or `--publish=SPEC` — see [Binding container ports](#binding-ports) @@ -537,9 +540,15 @@ The steps with which Docker configures a container are: separate and unique network interface namespace, there are no physical interfaces with which this name could collide. -4. Give the container's `eth0` a new IP address from within the +4. Set the interface's mac address according to the `--mac-address` + parameter or generate a random one. + +5. Give the container's `eth0` a new IP address from within the bridge's range of network addresses, and set its default route to - the IP address that the Docker host owns on the bridge. + the IP address that the Docker host owns on the bridge. If available + the IP address is generated from the MAC address. This prevents arp + cache invalidation problems, when a new container comes up with an + IP used in the past by another container with another MAC. With these steps complete, the container now possesses an `eth0` (virtual) network card and will find itself able to communicate with @@ -621,6 +630,7 @@ Docker do all of the configuration: $ sudo ip link set B netns $pid $ sudo ip netns exec $pid ip link set dev B name eth0 + $ sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc $ sudo ip netns exec $pid ip link set eth0 up $ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0 $ sudo ip netns exec $pid ip route add default via 172.17.42.1 diff --git a/components/engine/docs/sources/reference/api/docker_remote_api.md b/components/engine/docs/sources/reference/api/docker_remote_api.md index 559b841cde..5b054c6bbe 100644 --- a/components/engine/docs/sources/reference/api/docker_remote_api.md +++ b/components/engine/docs/sources/reference/api/docker_remote_api.md @@ -52,6 +52,10 @@ You can still call an old version of the API using `info` now returns the number of CPUs available on the machine (`NCPU`) and total memory available (`MemTotal`). +`POST /containers/create` +**New!** +You can define the container's MAC address by providing a MacAddress key-value pair. + ## v1.15 ### Full Documentation diff --git a/components/engine/docs/sources/reference/api/docker_remote_api_v1.15.md b/components/engine/docs/sources/reference/api/docker_remote_api_v1.15.md index cf8f6d3cc3..1b185db4de 100644 --- a/components/engine/docs/sources/reference/api/docker_remote_api_v1.15.md +++ b/components/engine/docs/sources/reference/api/docker_remote_api_v1.15.md @@ -131,6 +131,7 @@ Create a container }, "WorkingDir":"", "NetworkDisabled": false, + "MacAddress":"12:34:56:78:9a:bc", "ExposedPorts":{ "22/tcp": {} }, diff --git a/components/engine/docs/sources/reference/api/docker_remote_api_v1.16.md b/components/engine/docs/sources/reference/api/docker_remote_api_v1.16.md index fbb89294e2..81fdc7380a 100644 --- a/components/engine/docs/sources/reference/api/docker_remote_api_v1.16.md +++ b/components/engine/docs/sources/reference/api/docker_remote_api_v1.16.md @@ -131,6 +131,7 @@ Create a container }, "WorkingDir":"", "NetworkDisabled": false, + "MacAddress":"12:34:56:78:9a:bc", "ExposedPorts":{ "22/tcp": {} }, diff --git a/components/engine/docs/sources/reference/commandline/cli.md b/components/engine/docs/sources/reference/commandline/cli.md index a46ef6e3b6..50c0ff3cce 100644 --- a/components/engine/docs/sources/reference/commandline/cli.md +++ b/components/engine/docs/sources/reference/commandline/cli.md @@ -516,6 +516,7 @@ Creates a new container. --lxc-conf=[] (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" -m, --memory="" Memory limit (format: , where unit = b, k, m or g) --name="" Assign a name to the container + --mac-address="" Set the container's MAC address --net="bridge" Set the Network mode for the container 'bridge': creates a new network stack for the container on the docker bridge 'none': no networking for this container @@ -867,6 +868,13 @@ straightforward manner. $ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' $INSTANCE_ID +**Get an instance's MAC Address:** + +For the most part, you can pick out any field from the JSON in a fairly +straightforward manner. + + $ sudo docker inspect --format='{{.NetworkSettings.MacAddress}}' $INSTANCE_ID + **List All Port Bindings:** One can loop over arrays and maps in the results to produce simple text diff --git a/components/engine/docs/sources/reference/run.md b/components/engine/docs/sources/reference/run.md index b17afde23f..c8a141de06 100644 --- a/components/engine/docs/sources/reference/run.md +++ b/components/engine/docs/sources/reference/run.md @@ -133,13 +133,14 @@ example, `docker run ubuntu:14.04`. ## Network settings - --dns=[] : Set custom dns servers for the container - --net="bridge" : Set the Network mode for the container - 'bridge': creates a new network stack for the container on the docker bridge - 'none': no networking for this container - 'container:': reuses another container network stack - 'host': use the host network stack inside the container - --add-host="" : Add a line to /etc/hosts (host:IP) + --dns=[] : Set custom dns servers for the container + --net="bridge" : Set the Network mode for the container + 'bridge': creates a new network stack for the container on the docker bridge + 'none': no networking for this container + 'container:': reuses another container network stack + 'host': use the host network stack inside the container + --add-host="" : Add a line to /etc/hosts (host:IP) + --mac-address="" : Sets the container's ethernet device's mac address By default, all containers have networking enabled and they can make any outgoing connections. The operator can completely disable networking @@ -150,6 +151,10 @@ networking. In cases like this, you would perform I/O through files or Your container will use the same DNS servers as the host by default, but you can override this with `--dns`. +By default a random mac is generated. You can set the container's mac address +explicitly by providing a mac via the `--mac-address` parameter (format: +12:34:56:78:9a:bc). + Supported networking modes are: * none - no networking in the container diff --git a/components/engine/integration-cli/docker_cli_run_test.go b/components/engine/integration-cli/docker_cli_run_test.go index c529be7df2..389bcda93a 100644 --- a/components/engine/integration-cli/docker_cli_run_test.go +++ b/components/engine/integration-cli/docker_cli_run_test.go @@ -2018,6 +2018,41 @@ func TestRunNetworkNotInitializedNoneMode(t *testing.T) { logDone("run - network must not be initialized in 'none' mode") } +func TestRunSetMacAddress(t *testing.T) { + mac := "12:34:56:78:9a:bc" + cmd := exec.Command("/bin/bash", "-c", dockerBinary+` run -i --rm --mac-address=`+mac+` busybox /bin/sh -c "ip link show eth0 | tail -1 | awk '{ print \$2 }'"`) + out, _, err := runCommandWithOutput(cmd) + if err != nil { + t.Fatal(err) + } + actualMac := strings.TrimSpace(out) + if actualMac != mac { + t.Fatalf("Set Mac Address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac) + } + + deleteAllContainers() + logDone("run - setting Mac Address with --mac-address") +} + +func TestRunInspectMacAddress(t *testing.T) { + mac := "12:34:56:78:9a:bc" + cmd := exec.Command(dockerBinary, "run", "-d", "--mac-address="+mac, "busybox", "top") + out, _, err := runCommandWithOutput(cmd) + if err != nil { + t.Fatal(err) + } + id := strings.TrimSpace(out) + inspectedMac, err := inspectField(id, "NetworkSettings.MacAddress") + if err != nil { + t.Fatal(err) + } + if inspectedMac != mac { + t.Fatalf("Inspecting Mac Address with failed. docker inspect shows incorrect MacAddress: %q, actual Mac: %q", inspectedMac, mac) + } + deleteAllContainers() + logDone("run - inspecting Mac Address") +} + func TestRunDeallocatePortOnMissingIptablesRule(t *testing.T) { cmd := exec.Command(dockerBinary, "run", "-d", "-p", "23:23", "busybox", "top") out, _, err := runCommandWithOutput(cmd) diff --git a/components/engine/runconfig/config.go b/components/engine/runconfig/config.go index 28e85de647..29c54a4d6d 100644 --- a/components/engine/runconfig/config.go +++ b/components/engine/runconfig/config.go @@ -31,6 +31,7 @@ type Config struct { WorkingDir string Entrypoint []string NetworkDisabled bool + MacAddress string OnBuild []string SecurityOpt []string } @@ -53,6 +54,7 @@ func ContainerConfigFromJob(job *engine.Job) *Config { Image: job.Getenv("Image"), WorkingDir: job.Getenv("WorkingDir"), NetworkDisabled: job.GetenvBool("NetworkDisabled"), + MacAddress: job.Getenv("MacAddress"), } job.GetenvJson("ExposedPorts", &config.ExposedPorts) job.GetenvJson("Volumes", &config.Volumes) diff --git a/components/engine/runconfig/parse.go b/components/engine/runconfig/parse.go index 9635e9402d..aed10eadd1 100644 --- a/components/engine/runconfig/parse.go +++ b/components/engine/runconfig/parse.go @@ -59,6 +59,7 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") flCpuset = cmd.String([]string{"-cpuset"}, "", "CPUs in which to allow execution (0-3, 0,1)") flNetMode = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container\n'bridge': creates a new network stack for the container on the docker bridge\n'none': no networking for this container\n'container:': reuses another container network stack\n'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.") + flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (ex: 92:d0:c6:0a:29:33)") flRestartPolicy = cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)") ) @@ -269,6 +270,7 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, Cmd: runCmd, Image: image, Volumes: flVolumes.GetMap(), + MacAddress: *flMacAddress, Entrypoint: entrypoint, WorkingDir: *flWorkingDir, SecurityOpt: flSecurityOpt.GetAll(), From 590a54ca61a743e48ba37cf074e7dc2f4552fd1f Mon Sep 17 00:00:00 2001 From: Malte Janduda Date: Mon, 3 Nov 2014 11:43:11 +0100 Subject: [PATCH 2/3] enhancing set-macaddress docu Signed-off-by: Malte Janduda Upstream-commit: 971fc2253af77ae4a22a3741fff51d84cd9bc697 Component: engine --- components/engine/docs/man/docker-run.1.md | 2 +- components/engine/docs/sources/articles/networking.md | 6 +++--- .../docs/sources/reference/api/docker_remote_api.md | 2 +- components/engine/docs/sources/reference/run.md | 8 ++++---- components/engine/integration-cli/docker_cli_run_test.go | 8 ++++---- components/engine/runconfig/parse.go | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/components/engine/docs/man/docker-run.1.md b/components/engine/docs/man/docker-run.1.md index ce2ffeb434..ae559819b1 100644 --- a/components/engine/docs/man/docker-run.1.md +++ b/components/engine/docs/man/docker-run.1.md @@ -192,7 +192,7 @@ and foreground Docker containers. Set the MAC address for the container's ethernet device: --mac-address=12:34:56:78:9a:bc -Remember that the MAC address in an ethernet network must be unique. +Remember that the MAC address in an Ethernet network must be unique. The IPv6 link-local address will be based on the device's MAC address according to RFC4862. diff --git a/components/engine/docs/sources/articles/networking.md b/components/engine/docs/sources/articles/networking.md index 49f3722216..6587efc522 100644 --- a/components/engine/docs/sources/articles/networking.md +++ b/components/engine/docs/sources/articles/networking.md @@ -105,7 +105,7 @@ Finally, several networking options can only be provided when calling [How Docker networks a container](#container-networking) * `--mac-address=MACADDRESS...` — see - [How docker networks a container](#container-networking) + [How Docker networks a container](#container-networking) * `-p SPEC` or `--publish=SPEC` — see [Binding container ports](#binding-ports) @@ -540,13 +540,13 @@ The steps with which Docker configures a container are: separate and unique network interface namespace, there are no physical interfaces with which this name could collide. -4. Set the interface's mac address according to the `--mac-address` +4. Set the interface's MAC address according to the `--mac-address` parameter or generate a random one. 5. Give the container's `eth0` a new IP address from within the bridge's range of network addresses, and set its default route to the IP address that the Docker host owns on the bridge. If available - the IP address is generated from the MAC address. This prevents arp + the IP address is generated from the MAC address. This prevents ARP cache invalidation problems, when a new container comes up with an IP used in the past by another container with another MAC. diff --git a/components/engine/docs/sources/reference/api/docker_remote_api.md b/components/engine/docs/sources/reference/api/docker_remote_api.md index 5b054c6bbe..3babab8eca 100644 --- a/components/engine/docs/sources/reference/api/docker_remote_api.md +++ b/components/engine/docs/sources/reference/api/docker_remote_api.md @@ -54,7 +54,7 @@ total memory available (`MemTotal`). `POST /containers/create` **New!** -You can define the container's MAC address by providing a MacAddress key-value pair. +You can set the new container's MAC address explicitly. ## v1.15 diff --git a/components/engine/docs/sources/reference/run.md b/components/engine/docs/sources/reference/run.md index c8a141de06..4ec867f1a6 100644 --- a/components/engine/docs/sources/reference/run.md +++ b/components/engine/docs/sources/reference/run.md @@ -140,7 +140,7 @@ example, `docker run ubuntu:14.04`. 'container:': reuses another container network stack 'host': use the host network stack inside the container --add-host="" : Add a line to /etc/hosts (host:IP) - --mac-address="" : Sets the container's ethernet device's mac address + --mac-address="" : Sets the container's ethernet device's MAC address By default, all containers have networking enabled and they can make any outgoing connections. The operator can completely disable networking @@ -151,9 +151,9 @@ networking. In cases like this, you would perform I/O through files or Your container will use the same DNS servers as the host by default, but you can override this with `--dns`. -By default a random mac is generated. You can set the container's mac address -explicitly by providing a mac via the `--mac-address` parameter (format: -12:34:56:78:9a:bc). +By default a random MAC is generated. You can set the container's MAC address +explicitly by providing a MAC via the `--mac-address` parameter (format: +`12:34:56:78:9a:bc`). Supported networking modes are: diff --git a/components/engine/integration-cli/docker_cli_run_test.go b/components/engine/integration-cli/docker_cli_run_test.go index 389bcda93a..4c3e8d0a08 100644 --- a/components/engine/integration-cli/docker_cli_run_test.go +++ b/components/engine/integration-cli/docker_cli_run_test.go @@ -2027,11 +2027,11 @@ func TestRunSetMacAddress(t *testing.T) { } actualMac := strings.TrimSpace(out) if actualMac != mac { - t.Fatalf("Set Mac Address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac) + t.Fatalf("Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac) } deleteAllContainers() - logDone("run - setting Mac Address with --mac-address") + logDone("run - setting MAC address with --mac-address") } func TestRunInspectMacAddress(t *testing.T) { @@ -2047,10 +2047,10 @@ func TestRunInspectMacAddress(t *testing.T) { t.Fatal(err) } if inspectedMac != mac { - t.Fatalf("Inspecting Mac Address with failed. docker inspect shows incorrect MacAddress: %q, actual Mac: %q", inspectedMac, mac) + t.Fatalf("docker inspect outputs wrong MAC address: %q, should be: %q", inspectedMac, mac) } deleteAllContainers() - logDone("run - inspecting Mac Address") + logDone("run - inspecting MAC address") } func TestRunDeallocatePortOnMissingIptablesRule(t *testing.T) { diff --git a/components/engine/runconfig/parse.go b/components/engine/runconfig/parse.go index aed10eadd1..c62ab3fdd4 100644 --- a/components/engine/runconfig/parse.go +++ b/components/engine/runconfig/parse.go @@ -59,7 +59,7 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") flCpuset = cmd.String([]string{"-cpuset"}, "", "CPUs in which to allow execution (0-3, 0,1)") flNetMode = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container\n'bridge': creates a new network stack for the container on the docker bridge\n'none': no networking for this container\n'container:': reuses another container network stack\n'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.") - flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (ex: 92:d0:c6:0a:29:33)") + flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)") flRestartPolicy = cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)") ) From d1a9c32b506cc62b4348b7023f8e97a6907e4011 Mon Sep 17 00:00:00 2001 From: Malte Janduda Date: Tue, 4 Nov 2014 15:19:47 +0100 Subject: [PATCH 3/3] enhancing set-macaddress docu #2 Signed-off-by: Malte Janduda Upstream-commit: 28605bc4d55bcfc7a5562e4de3e01b1d5cd9bdcd Component: engine --- components/engine/docs/man/docker-run.1.md | 2 +- components/engine/docs/sources/reference/run.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/engine/docs/man/docker-run.1.md b/components/engine/docs/man/docker-run.1.md index ae559819b1..ff3dac17b0 100644 --- a/components/engine/docs/man/docker-run.1.md +++ b/components/engine/docs/man/docker-run.1.md @@ -189,7 +189,7 @@ and foreground Docker containers. 'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. **--mac-address**=*macaddress* - Set the MAC address for the container's ethernet device: + Set the MAC address for the container's Ethernet device: --mac-address=12:34:56:78:9a:bc Remember that the MAC address in an Ethernet network must be unique. diff --git a/components/engine/docs/sources/reference/run.md b/components/engine/docs/sources/reference/run.md index 4ec867f1a6..826e1c8b6c 100644 --- a/components/engine/docs/sources/reference/run.md +++ b/components/engine/docs/sources/reference/run.md @@ -140,7 +140,7 @@ example, `docker run ubuntu:14.04`. 'container:': reuses another container network stack 'host': use the host network stack inside the container --add-host="" : Add a line to /etc/hosts (host:IP) - --mac-address="" : Sets the container's ethernet device's MAC address + --mac-address="" : Sets the container's Ethernet device's MAC address By default, all containers have networking enabled and they can make any outgoing connections. The operator can completely disable networking