fix: apply the daemon's mtu to job networks (#1270)

Copy the `mtu` of Docker's default bridge network to job networks, since Docker applies the daemon's `mtu` setting only to the default bridge. Docker's default of 1500 is not copied, so `default-network-opts` in the daemon config keeps applying.

Closes https://gitea.com/gitea/runner/issues/232

---------

Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1270
Reviewed-by: silverwind <[email protected]>
Co-authored-by: bircni <[email protected]>
This commit is contained in:
authored and silverwind committed 2026-10-08 17:39:54 +00:00
1 parent 329115b148
commit e5aa9add02
4 files changed
+37 -1

No files matched your search

+10 -1
View File
@@ -87,12 +87,17 @@ func NewDockerNetworkCreateExecutor(name string, opts NewDockerNetworkCreateExec
return err return err
} }
defer cli.Close() defer cli.Close()
return createDockerNetwork(ctx, cli, name, opts)
}
}
func createDockerNetwork(ctx context.Context, cli client.APIClient, name string, opts NewDockerNetworkCreateExecutorInput) error {
// Only create the network if it doesn't exist // Only create the network if it doesn't exist
networks, err := cli.NetworkList(ctx, client.NetworkListOptions{}) networks, err := cli.NetworkList(ctx, client.NetworkListOptions{})
if err != nil { if err != nil {
return err return err
} }
var options map[string]string
// For Gitea, reduce log noise // For Gitea, reduce log noise
// common.Logger(ctx).Debugf("%v", networks) // common.Logger(ctx).Debugf("%v", networks)
for _, n := range networks.Items { for _, n := range networks.Items {
@@ -100,6 +105,10 @@ func NewDockerNetworkCreateExecutor(name string, opts NewDockerNetworkCreateExec
common.Logger(ctx).Debugf("Network %v exists", name) common.Logger(ctx).Debugf("Network %v exists", name)
return nil return nil
} }
// the daemon's mtu only reaches its default bridge, Docker's default is left out to keep default-network-opts
if mtu := n.Options["com.docker.network.driver.mtu"]; n.Name == network.NetworkBridge && mtu != "" && mtu != "1500" {
options = map[string]string{"com.docker.network.driver.mtu": mtu}
}
} }
for i := range networkCreateAttempts { for i := range networkCreateAttempts {
@@ -116,6 +125,7 @@ func NewDockerNetworkCreateExecutor(name string, opts NewDockerNetworkCreateExec
Scope: "local", Scope: "local",
EnableIPv4: opts.EnableIPv4, EnableIPv4: opts.EnableIPv4,
EnableIPv6: opts.EnableIPv6, EnableIPv6: opts.EnableIPv6,
Options: options,
Labels: runnerLabels(opts.RunnerUUID), Labels: runnerLabels(opts.RunnerUUID),
}); err == nil { }); err == nil {
return nil return nil
@@ -126,7 +136,6 @@ func NewDockerNetworkCreateExecutor(name string, opts NewDockerNetworkCreateExec
} }
return fmt.Errorf("docker has no address pool left for this job's network, lower runner.capacity or widen default-address-pools in the docker daemon config: %w", err) return fmt.Errorf("docker has no address pool left for this job's network, lower runner.capacity or widen default-address-pools in the docker daemon config: %w", err)
} }
}
func runnerLabels(runnerUUID string) map[string]string { func runnerLabels(runnerUUID string) map[string]string {
if runnerUUID == "" { if runnerUUID == "" {
+21
View File
@@ -57,6 +57,27 @@ func TestIsAddressPoolExhausted(t *testing.T) {
assert.False(t, isAddressPoolExhausted(cerrdefs.ErrInvalidArgument.WithMessage("invalid subnet 10.0.0.0/8: it overlaps with an existing network"))) assert.False(t, isAddressPoolExhausted(cerrdefs.ErrInvalidArgument.WithMessage("invalid subnet 10.0.0.0/8: it overlaps with an existing network")))
} }
func TestCreateDockerNetworkInheritsDaemonMTU(t *testing.T) {
ctx := context.Background()
for _, tc := range []struct {
bridgeOptions, want map[string]string
}{
{
map[string]string{"com.docker.network.bridge.host_binding_ipv4": "127.0.0.1", "com.docker.network.driver.mtu": "1450"},
map[string]string{"com.docker.network.driver.mtu": "1450"},
},
{map[string]string{"com.docker.network.driver.mtu": "1500"}, nil},
} {
client := &mockDockerClient{}
client.On("NetworkList", ctx, mobyclient.NetworkListOptions{}).
Return(mobyclient.NetworkListResult{Items: []network.Summary{{Name: network.NetworkBridge, Options: tc.bridgeOptions}}}, nil)
client.On("NetworkCreate", ctx, "job-network", mobyclient.NetworkCreateOptions{Driver: "bridge", Scope: "local", Options: tc.want}).
Return(mobyclient.NetworkCreateResult{}, nil)
require.NoError(t, createDockerNetwork(ctx, client, "job-network", NewDockerNetworkCreateExecutorInput{}))
client.AssertExpectations(t)
}
}
func (m *mockDockerClient) NetworkConnect(ctx context.Context, id string, opts mobyclient.NetworkConnectOptions) (mobyclient.NetworkConnectResult, error) { func (m *mockDockerClient) NetworkConnect(ctx context.Context, id string, opts mobyclient.NetworkConnectOptions) (mobyclient.NetworkConnectResult, error) {
return mobyclient.NetworkConnectResult{}, m.Called(ctx, id, opts).Error(0) return mobyclient.NetworkConnectResult{}, m.Called(ctx, id, opts).Error(0)
} }
+5
View File
@@ -137,6 +137,11 @@ func (m *mockDockerClient) NetworkList(ctx context.Context, opts mobyclient.Netw
return args.Get(0).(mobyclient.NetworkListResult), args.Error(1) return args.Get(0).(mobyclient.NetworkListResult), args.Error(1)
} }
func (m *mockDockerClient) NetworkCreate(ctx context.Context, name string, opts mobyclient.NetworkCreateOptions) (mobyclient.NetworkCreateResult, error) {
args := m.Called(ctx, name, opts)
return args.Get(0).(mobyclient.NetworkCreateResult), args.Error(1)
}
func (m *mockDockerClient) NetworkInspect(ctx context.Context, id string, opts mobyclient.NetworkInspectOptions) (mobyclient.NetworkInspectResult, error) { func (m *mockDockerClient) NetworkInspect(ctx context.Context, id string, opts mobyclient.NetworkInspectOptions) (mobyclient.NetworkInspectResult, error) {
args := m.Called(ctx, id, opts) args := m.Called(ctx, id, opts)
return args.Get(0).(mobyclient.NetworkInspectResult), args.Error(1) return args.Get(0).(mobyclient.NetworkInspectResult), args.Error(1)
+1
View File
@@ -223,6 +223,7 @@ container:
# created by the runner. Omit the entire block to use Docker's defaults. An auto-created # created by the runner. Omit the entire block to use Docker's defaults. An auto-created
# network is labelled com.gitea.runner.uuid=<this runner's uuid>, which is how the idle # network is labelled com.gitea.runner.uuid=<this runner's uuid>, which is how the idle
# cleanup tells its own leftovers apart from those of other runners on the same daemon. # cleanup tells its own leftovers apart from those of other runners on the same daemon.
# It also takes the `mtu` set in the Docker daemon config.
#network_create_options: #network_create_options:
# enable_ipv4: true # Omit to use Docker's default (IPv4 enabled). Set false to disable IPv4. # enable_ipv4: true # Omit to use Docker's default (IPv4 enabled). Set false to disable IPv4.
# enable_ipv6: false # Omit to use Docker's default (IPv6 disabled). Enabling it requires dockerd started with --ipv6. # enable_ipv6: false # Omit to use Docker's default (IPv6 disabled). Enabling it requires dockerd started with --ipv6.