From 82486654c0b049f9b709c7e445d5ab0819720680 Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Mon, 8 Apr 2024 09:22:08 +0100 Subject: [PATCH] Add '--sysctl' option to 'network connect' Equivalent to 'sysctl' in the extended 'run --network' syntax. Signed-off-by: Rob Murray --- cli/command/network/connect.go | 9 ++++- cli/command/network/connect_test.go | 6 ++- docs/reference/commandline/network_connect.md | 38 +++++++++++++++---- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/cli/command/network/connect.go b/cli/command/network/connect.go index 6ffb9b8dcf2d..8abe4b4b01e8 100644 --- a/cli/command/network/connect.go +++ b/cli/command/network/connect.go @@ -22,6 +22,7 @@ type connectOptions struct { aliases []string linklocalips []string driverOpts []string + sysctls []string } func newConnectCommand(dockerCli command.Cli) *cobra.Command { @@ -54,13 +55,14 @@ func newConnectCommand(dockerCli command.Cli) *cobra.Command { flags.StringSliceVar(&options.aliases, "alias", []string{}, "Add network-scoped alias for the container") flags.StringSliceVar(&options.linklocalips, "link-local-ip", []string{}, "Add a link-local address for the container") flags.StringSliceVar(&options.driverOpts, "driver-opt", []string{}, "driver options for the network") + flags.StringSliceVar(&options.sysctls, "sysctl", []string{}, "short-form interface sysctl: net.X.Y.ethN.Z=V -> X.Y.Z=V") return cmd } func runConnect(ctx context.Context, dockerCli command.Cli, options connectOptions) error { client := dockerCli.Client() - driverOpts, err := convertDriverOpt(options.driverOpts) + driverOpts, err := convertDriverOpt(options.driverOpts, options.sysctls) if err != nil { return err } @@ -78,7 +80,7 @@ func runConnect(ctx context.Context, dockerCli command.Cli, options connectOptio return client.NetworkConnect(ctx, options.network, options.container, epConfig) } -func convertDriverOpt(options []string) (map[string]string, error) { +func convertDriverOpt(options []string, sysctls []string) (map[string]string, error) { driverOpt := make(map[string]string) for _, opt := range options { k, v, ok := strings.Cut(opt, "=") @@ -89,5 +91,8 @@ func convertDriverOpt(options []string) (map[string]string, error) { } driverOpt[k] = strings.TrimSpace(v) } + if len(sysctls) > 0 { + driverOpt[opts.NetlabelEpSysctls] = strings.Join(sysctls, ",") + } return driverOpt, nil } diff --git a/cli/command/network/connect_test.go b/cli/command/network/connect_test.go index 1ba9d1df5a2f..704b2bce44be 100644 --- a/cli/command/network/connect_test.go +++ b/cli/command/network/connect_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/docker/cli/internal/test" + "github.com/docker/cli/opts" "github.com/docker/docker/api/types/network" "github.com/pkg/errors" "gotest.tools/v3/assert" @@ -52,7 +53,8 @@ func TestNetworkConnectWithFlags(t *testing.T) { Links: []string{"otherctr"}, Aliases: []string{"poor-yorick"}, DriverOpts: map[string]string{ - "adriveropt": "anoptval", + "adriveropt": "anoptval", + opts.NetlabelEpSysctls: "ipv6.conf.accept_ra=2,ipv6.conf.forwarding=1", }, } cli := test.NewFakeCli(&fakeClient{ @@ -72,6 +74,8 @@ func TestNetworkConnectWithFlags(t *testing.T) { {"ip6", "fdef:f401:8da0:1234::5678"}, {"link", "otherctr"}, {"link-local-ip", "169.254.42.42"}, + {"sysctl", "ipv6.conf.accept_ra=2"}, + {"sysctl", "ipv6.conf.forwarding=1"}, } { err := cmd.Flags().Set(opt.name, opt.value) assert.Check(t, err) diff --git a/docs/reference/commandline/network_connect.md b/docs/reference/commandline/network_connect.md index e2496503c624..b77851506bbb 100644 --- a/docs/reference/commandline/network_connect.md +++ b/docs/reference/commandline/network_connect.md @@ -5,14 +5,15 @@ Connect a container to a network ### Options -| Name | Type | Default | Description | -|:--------------------|:--------------|:--------|:-------------------------------------------| -| [`--alias`](#alias) | `stringSlice` | | Add network-scoped alias for the container | -| `--driver-opt` | `stringSlice` | | driver options for the network | -| [`--ip`](#ip) | `string` | | IPv4 address (e.g., `172.30.100.104`) | -| `--ip6` | `string` | | IPv6 address (e.g., `2001:db8::33`) | -| [`--link`](#link) | `list` | | Add link to another container | -| `--link-local-ip` | `stringSlice` | | Add a link-local address for the container | +| Name | Type | Default | Description | +|:----------------------|:--------------|:--------|:---------------------------------------------------------| +| [`--alias`](#alias) | `stringSlice` | | Add network-scoped alias for the container | +| `--driver-opt` | `stringSlice` | | driver options for the network | +| [`--ip`](#ip) | `string` | | IPv4 address (e.g., `172.30.100.104`) | +| `--ip6` | `string` | | IPv6 address (e.g., `2001:db8::33`) | +| [`--link`](#link) | `list` | | Add link to another container | +| `--link-local-ip` | `stringSlice` | | Add a link-local address for the container | +| [`--sysctl`](#sysctl) | `stringSlice` | | Short-form interface sysctl: net.X.Y.ethN.Z=V -> X.Y.Z=V | @@ -23,6 +24,14 @@ 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 the same network. +The `--sysctl` option in `network connect` is restricted to 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. + ## Examples ### Connect a running container to a network @@ -64,6 +73,19 @@ being connected to. ```console $ docker network connect --alias db --alias mysql multi-host-network container2 ``` +### Set a sysctl for a container's interface (--sysctl) + +`--sysctl` sets a network sysctl on the interface created to connect to the +network, only `net.ipv4.` and `net.ipv6.` settings can be modified. The +interface name is assigned automatically, so it must be left out along with +the `net.` prefix. + +If the network interface created in the container is called `eth3`, this +example is equivalent to `net.ipv4.conf.eth3.log_martians=1`. + +```console +$ docker network connect --sysctl ipv4.conf.log_martians=1 multi-host-network container2 +``` ### Network implications of stopping, pausing, or restarting containers