Adding docker-cli run param to set MAC address
| ... | ... |
@@ -457,6 +457,7 @@ func (container *Container) AllocateNetwork() error {
|
| 457 | 457 |
) |
| 458 | 458 |
|
| 459 | 459 |
job := eng.Job("allocate_interface", container.ID)
|
| 460 |
+ job.Setenv("RequestedMac", container.Config.MacAddress)
|
|
| 460 | 461 |
if env, err = job.Stdout.AddEnv(); err != nil {
|
| 461 | 462 |
return err |
| 462 | 463 |
} |
| ... | ... |
@@ -29,6 +29,7 @@ docker-run - Run a command in a new container |
| 29 | 29 |
[**-m**|**--memory**[=*MEMORY*]] |
| 30 | 30 |
[**--name**[=*NAME*]] |
| 31 | 31 |
[**--net**[=*"bridge"*]] |
| 32 |
+[**--mac-address**[=*MACADDRESS*]] |
|
| 32 | 33 |
[**-P**|**--publish-all**[=*false*]] |
| 33 | 34 |
[**-p**|**--publish**[=*[]*]] |
| 34 | 35 |
[**--privileged**[=*false*]] |
| ... | ... |
@@ -187,6 +188,14 @@ and foreground Docker containers. |
| 187 | 187 |
'container:<name|id>': reuses another container network stack |
| 188 | 188 |
'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. |
| 189 | 189 |
|
| 190 |
+**--mac-address**=*macaddress* |
|
| 191 |
+ Set the MAC address for the container's Ethernet device: |
|
| 192 |
+ --mac-address=12:34:56:78:9a:bc |
|
| 193 |
+ |
|
| 194 |
+Remember that the MAC address in an Ethernet network must be unique. |
|
| 195 |
+The IPv6 link-local address will be based on the device's MAC address |
|
| 196 |
+according to RFC4862. |
|
| 197 |
+ |
|
| 190 | 198 |
**-P**, **--publish-all**=*true*|*false* |
| 191 | 199 |
When set to true publish all exposed ports to the host interfaces. The |
| 192 | 200 |
default is false. If the operator uses -P (or -p) then Docker will make the |
| ... | ... |
@@ -104,6 +104,9 @@ Finally, several networking options can only be provided when calling |
| 104 | 104 |
* `--net=bridge|none|container:NAME_or_ID|host` — see |
| 105 | 105 |
[How Docker networks a container](#container-networking) |
| 106 | 106 |
|
| 107 |
+ * `--mac-address=MACADDRESS...` — see |
|
| 108 |
+ [How Docker networks a container](#container-networking) |
|
| 109 |
+ |
|
| 107 | 110 |
* `-p SPEC` or `--publish=SPEC` — see |
| 108 | 111 |
[Binding container ports](#binding-ports) |
| 109 | 112 |
|
| ... | ... |
@@ -537,9 +540,15 @@ The steps with which Docker configures a container are: |
| 537 | 537 |
separate and unique network interface namespace, there are no |
| 538 | 538 |
physical interfaces with which this name could collide. |
| 539 | 539 |
|
| 540 |
-4. Give the container's `eth0` a new IP address from within the |
|
| 540 |
+4. Set the interface's MAC address according to the `--mac-address` |
|
| 541 |
+ parameter or generate a random one. |
|
| 542 |
+ |
|
| 543 |
+5. Give the container's `eth0` a new IP address from within the |
|
| 541 | 544 |
bridge's range of network addresses, and set its default route to |
| 542 |
- the IP address that the Docker host owns on the bridge. |
|
| 545 |
+ the IP address that the Docker host owns on the bridge. If available |
|
| 546 |
+ the IP address is generated from the MAC address. This prevents ARP |
|
| 547 |
+ cache invalidation problems, when a new container comes up with an |
|
| 548 |
+ IP used in the past by another container with another MAC. |
|
| 543 | 549 |
|
| 544 | 550 |
With these steps complete, the container now possesses an `eth0` |
| 545 | 551 |
(virtual) network card and will find itself able to communicate with |
| ... | ... |
@@ -621,6 +630,7 @@ Docker do all of the configuration: |
| 621 | 621 |
|
| 622 | 622 |
$ sudo ip link set B netns $pid |
| 623 | 623 |
$ sudo ip netns exec $pid ip link set dev B name eth0 |
| 624 |
+ $ sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc |
|
| 624 | 625 |
$ sudo ip netns exec $pid ip link set eth0 up |
| 625 | 626 |
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0 |
| 626 | 627 |
$ sudo ip netns exec $pid ip route add default via 172.17.42.1 |
| ... | ... |
@@ -52,6 +52,10 @@ You can still call an old version of the API using |
| 52 | 52 |
`info` now returns the number of CPUs available on the machine (`NCPU`) and |
| 53 | 53 |
total memory available (`MemTotal`). |
| 54 | 54 |
|
| 55 |
+`POST /containers/create` |
|
| 56 |
+**New!** |
|
| 57 |
+You can set the new container's MAC address explicitly. |
|
| 58 |
+ |
|
| 55 | 59 |
## v1.15 |
| 56 | 60 |
|
| 57 | 61 |
### Full Documentation |
| ... | ... |
@@ -516,6 +516,7 @@ Creates a new container. |
| 516 | 516 |
--lxc-conf=[] (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" |
| 517 | 517 |
-m, --memory="" Memory limit (format: <number><optional unit>, where unit = b, k, m or g) |
| 518 | 518 |
--name="" Assign a name to the container |
| 519 |
+ --mac-address="" Set the container's MAC address |
|
| 519 | 520 |
--net="bridge" Set the Network mode for the container |
| 520 | 521 |
'bridge': creates a new network stack for the container on the docker bridge |
| 521 | 522 |
'none': no networking for this container |
| ... | ... |
@@ -867,6 +868,13 @@ straightforward manner. |
| 867 | 867 |
|
| 868 | 868 |
$ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' $INSTANCE_ID
|
| 869 | 869 |
|
| 870 |
+**Get an instance's MAC Address:** |
|
| 871 |
+ |
|
| 872 |
+For the most part, you can pick out any field from the JSON in a fairly |
|
| 873 |
+straightforward manner. |
|
| 874 |
+ |
|
| 875 |
+ $ sudo docker inspect --format='{{.NetworkSettings.MacAddress}}' $INSTANCE_ID
|
|
| 876 |
+ |
|
| 870 | 877 |
**List All Port Bindings:** |
| 871 | 878 |
|
| 872 | 879 |
One can loop over arrays and maps in the results to produce simple text |
| ... | ... |
@@ -133,13 +133,14 @@ example, `docker run ubuntu:14.04`. |
| 133 | 133 |
|
| 134 | 134 |
## Network settings |
| 135 | 135 |
|
| 136 |
- --dns=[] : Set custom dns servers for the container |
|
| 137 |
- --net="bridge" : Set the Network mode for the container |
|
| 138 |
- 'bridge': creates a new network stack for the container on the docker bridge |
|
| 139 |
- 'none': no networking for this container |
|
| 140 |
- 'container:<name|id>': reuses another container network stack |
|
| 141 |
- 'host': use the host network stack inside the container |
|
| 142 |
- --add-host="" : Add a line to /etc/hosts (host:IP) |
|
| 136 |
+ --dns=[] : Set custom dns servers for the container |
|
| 137 |
+ --net="bridge" : Set the Network mode for the container |
|
| 138 |
+ 'bridge': creates a new network stack for the container on the docker bridge |
|
| 139 |
+ 'none': no networking for this container |
|
| 140 |
+ 'container:<name|id>': reuses another container network stack |
|
| 141 |
+ 'host': use the host network stack inside the container |
|
| 142 |
+ --add-host="" : Add a line to /etc/hosts (host:IP) |
|
| 143 |
+ --mac-address="" : Sets the container's Ethernet device's MAC address |
|
| 143 | 144 |
|
| 144 | 145 |
By default, all containers have networking enabled and they can make any |
| 145 | 146 |
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 |
| 150 | 150 |
Your container will use the same DNS servers as the host by default, but |
| 151 | 151 |
you can override this with `--dns`. |
| 152 | 152 |
|
| 153 |
+By default a random MAC is generated. You can set the container's MAC address |
|
| 154 |
+explicitly by providing a MAC via the `--mac-address` parameter (format: |
|
| 155 |
+`12:34:56:78:9a:bc`). |
|
| 156 |
+ |
|
| 153 | 157 |
Supported networking modes are: |
| 154 | 158 |
|
| 155 | 159 |
* none - no networking in the container |
| ... | ... |
@@ -2018,6 +2018,41 @@ func TestRunNetworkNotInitializedNoneMode(t *testing.T) {
|
| 2018 | 2018 |
logDone("run - network must not be initialized in 'none' mode")
|
| 2019 | 2019 |
} |
| 2020 | 2020 |
|
| 2021 |
+func TestRunSetMacAddress(t *testing.T) {
|
|
| 2022 |
+ mac := "12:34:56:78:9a:bc" |
|
| 2023 |
+ 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 }'"`)
|
|
| 2024 |
+ out, _, err := runCommandWithOutput(cmd) |
|
| 2025 |
+ if err != nil {
|
|
| 2026 |
+ t.Fatal(err) |
|
| 2027 |
+ } |
|
| 2028 |
+ actualMac := strings.TrimSpace(out) |
|
| 2029 |
+ if actualMac != mac {
|
|
| 2030 |
+ t.Fatalf("Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q", actualMac, mac)
|
|
| 2031 |
+ } |
|
| 2032 |
+ |
|
| 2033 |
+ deleteAllContainers() |
|
| 2034 |
+ logDone("run - setting MAC address with --mac-address")
|
|
| 2035 |
+} |
|
| 2036 |
+ |
|
| 2037 |
+func TestRunInspectMacAddress(t *testing.T) {
|
|
| 2038 |
+ mac := "12:34:56:78:9a:bc" |
|
| 2039 |
+ cmd := exec.Command(dockerBinary, "run", "-d", "--mac-address="+mac, "busybox", "top") |
|
| 2040 |
+ out, _, err := runCommandWithOutput(cmd) |
|
| 2041 |
+ if err != nil {
|
|
| 2042 |
+ t.Fatal(err) |
|
| 2043 |
+ } |
|
| 2044 |
+ id := strings.TrimSpace(out) |
|
| 2045 |
+ inspectedMac, err := inspectField(id, "NetworkSettings.MacAddress") |
|
| 2046 |
+ if err != nil {
|
|
| 2047 |
+ t.Fatal(err) |
|
| 2048 |
+ } |
|
| 2049 |
+ if inspectedMac != mac {
|
|
| 2050 |
+ t.Fatalf("docker inspect outputs wrong MAC address: %q, should be: %q", inspectedMac, mac)
|
|
| 2051 |
+ } |
|
| 2052 |
+ deleteAllContainers() |
|
| 2053 |
+ logDone("run - inspecting MAC address")
|
|
| 2054 |
+} |
|
| 2055 |
+ |
|
| 2021 | 2056 |
func TestRunDeallocatePortOnMissingIptablesRule(t *testing.T) {
|
| 2022 | 2057 |
cmd := exec.Command(dockerBinary, "run", "-d", "-p", "23:23", "busybox", "top") |
| 2023 | 2058 |
out, _, err := runCommandWithOutput(cmd) |
| ... | ... |
@@ -31,6 +31,7 @@ type Config struct {
|
| 31 | 31 |
WorkingDir string |
| 32 | 32 |
Entrypoint []string |
| 33 | 33 |
NetworkDisabled bool |
| 34 |
+ MacAddress string |
|
| 34 | 35 |
OnBuild []string |
| 35 | 36 |
SecurityOpt []string |
| 36 | 37 |
} |
| ... | ... |
@@ -53,6 +54,7 @@ func ContainerConfigFromJob(job *engine.Job) *Config {
|
| 53 | 53 |
Image: job.Getenv("Image"),
|
| 54 | 54 |
WorkingDir: job.Getenv("WorkingDir"),
|
| 55 | 55 |
NetworkDisabled: job.GetenvBool("NetworkDisabled"),
|
| 56 |
+ MacAddress: job.Getenv("MacAddress"),
|
|
| 56 | 57 |
} |
| 57 | 58 |
job.GetenvJson("ExposedPorts", &config.ExposedPorts)
|
| 58 | 59 |
job.GetenvJson("Volumes", &config.Volumes)
|
| ... | ... |
@@ -59,6 +59,7 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, |
| 59 | 59 |
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
| 60 | 60 |
flCpuset = cmd.String([]string{"-cpuset"}, "", "CPUs in which to allow execution (0-3, 0,1)")
|
| 61 | 61 |
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:<name|id>': 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.")
|
| 62 |
+ flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
|
|
| 62 | 63 |
flRestartPolicy = cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)")
|
| 63 | 64 |
) |
| 64 | 65 |
|
| ... | ... |
@@ -269,6 +270,7 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, |
| 269 | 269 |
Cmd: runCmd, |
| 270 | 270 |
Image: image, |
| 271 | 271 |
Volumes: flVolumes.GetMap(), |
| 272 |
+ MacAddress: *flMacAddress, |
|
| 272 | 273 |
Entrypoint: entrypoint, |
| 273 | 274 |
WorkingDir: *flWorkingDir, |
| 274 | 275 |
SecurityOpt: flSecurityOpt.GetAll(), |