Skip to content

Commit

Permalink
Add 'sysctl' to the create/run '--network' syntax.
Browse files Browse the repository at this point in the history
Make it possible to set a per-interface sysctl using the extended
'--network' syntax in container create/run commands.

Settings are accumulated over multiple sysctl options and passed to the
API in DriverOpts, with key "com.docker.network.endpoint.sysctls", as
a comma-separated list.

Signed-off-by: Rob Murray <rob.murray@docker.com>
  • Loading branch information
robmry committed Apr 8, 2024
1 parent 18dafc4 commit 4e9d666
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
20 changes: 17 additions & 3 deletions docs/reference/commandline/container_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -757,16 +757,30 @@ $ docker run -itd --network=my-net1 --network=my-net2 busybox
```

When connecting to more than one network, use the extended syntax for
`--network` to supply options. Comma-separated options that can be specified
in the extended `--network` syntax are `name`, which is mandatory, `alias`,
`ip`, `ip6`, `mac-address`, `link-local-ip` and `driver-opt`.
`--network` to supply options. Comma-separated options that can be
specified in the extended `--network` syntax are `name`, which is mandatory,
`alias`, `ip`, `ip6`, `mac-address`, `link-local-ip`, `sysctl` and
`driver-opt`.

```console
$ docker network create --subnet 192.0.2.0/24 my-net1
$ docker network create --subnet 192.0.3.0/24 my-net2
$ docker run -itd --network=name=my-net1,ip=192.0.2.42 --network=name=my-net2,ip=192.0.3.42 busybox
```

The `sysctl` option is only available in the extended syntax, and it can only be
used for sysctls that start with `net.ipv4.` and `net.ipv6.`. The `net.` prefix
and the name of the interface must not be included. Internally, the sysctl options
are added to `DriverOpts` with the key `com.docker.network.endpoint.sysctls`, which
is where you'll find them in `docker inspect` output. Network drivers may restrict
the sysctl settings that can be modified and, to protect the operation of the
network, new restrictions may be added in the future.

```console
$ docker network create --subnet 192.0.2.0/24 my-net
$ docker run -itd --network=name=my-net,sysctl=ipv4.conf.log_martians=1,ip=192.0.2.42 busybox
```

For more information on connecting a container to a network when using the `run` command, see the ["*Docker network overview*"](https://docs.docker.com/network/).

### <a name="volumes-from"></a> Mount volumes from container (--volumes-from)
Expand Down
21 changes: 21 additions & 0 deletions opts/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ const (
networkOptIPv6Address = "ip6"
networkOptMacAddress = "mac-address"
networkOptLinkLocalIP = "link-local-ip"
driverOptSysctl = "sysctl"
driverOpt = "driver-opt"
)

// NetlabelEpSysctls is the label for short-form per-interface sysctls in DriverOpts.
// (A comma separated list of k=v pairs, where keys are sysctl names that omit an
// initial 'net.' and the interface name.)
const NetlabelEpSysctls = "com.docker.network.endpoint.sysctls"

// NetworkAttachmentOpts represents the network options for endpoint creation
type NetworkAttachmentOpts struct {
Target string
Expand All @@ -27,6 +33,7 @@ type NetworkAttachmentOpts struct {
IPv6Address string
LinkLocalIPs []string
MacAddress string
Sysctls []string
}

// NetworkOpt represents a network config in swarm mode.
Expand Down Expand Up @@ -73,6 +80,20 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
netOpt.MacAddress = val
case networkOptLinkLocalIP:
netOpt.LinkLocalIPs = append(netOpt.LinkLocalIPs, val)
case driverOptSysctl:
if skey, sval, ok := strings.Cut(val, "="); !ok {
return fmt.Errorf("invalid sysctl setting %s", val)
} else {
if netOpt.DriverOpts == nil {
netOpt.DriverOpts = make(map[string]string)
}
sysctls := netOpt.DriverOpts[NetlabelEpSysctls]
if sysctls != "" {
sysctls += ","
}
sysctls += strings.TrimSpace(skey) + "=" + strings.TrimSpace(sval)
netOpt.DriverOpts[NetlabelEpSysctls] = sysctls
}
case driverOpt:
key, val, err = parseDriverOpt(val)
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions opts/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ func TestNetworkOptAdvancedSyntax(t *testing.T) {
},
},
},
{
value: "name=docknet1,sysctl=ipv6.conf.accept_ra=2,sysctl=ipv6.conf.forwarding=1",
expected: []NetworkAttachmentOpts{
{
Target: "docknet1",
Aliases: []string{},
DriverOpts: map[string]string{
NetlabelEpSysctls: "ipv6.conf.accept_ra=2,ipv6.conf.forwarding=1",
},
},
},
},
}
for _, tc := range testCases {
tc := tc
Expand Down Expand Up @@ -126,6 +138,10 @@ func TestNetworkOptAdvancedSyntaxInvalid(t *testing.T) {
value: "driver-opt=field1=value1,driver-opt=field2=value2",
expectedError: "network name/id is not specified",
},
{
value: "name=docknet1,sysctl=ipv6.conf.accept_ra",
expectedError: "invalid sysctl setting ipv6.conf.accept_ra",
},
}
for _, tc := range testCases {
tc := tc
Expand Down

0 comments on commit 4e9d666

Please sign in to comment.