Skip to content

Commit f5e2cc1

Browse files
committed
introduce networks.interface_name
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent 60385e6 commit f5e2cc1

File tree

6 files changed

+68
-19
lines changed

6 files changed

+68
-19
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/Microsoft/go-winio v0.6.2
99
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
1010
github.com/buger/goterm v1.0.4
11-
github.com/compose-spec/compose-go/v2 v2.6.1
11+
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76
1212
github.com/containerd/containerd/v2 v2.0.5
1313
github.com/containerd/platforms v1.0.0-rc.1
1414
github.com/davecgh/go-spew v1.1.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e
8282
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
8383
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
8484
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
85-
github.com/compose-spec/compose-go/v2 v2.6.1 h1:276YiQKRcGGtgkxiymzWHJ2CTv5joQA+7DTNrUA+rys=
86-
github.com/compose-spec/compose-go/v2 v2.6.1/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
85+
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76 h1:KZvD41eTRr9/n43zccAcGPBRgzHXdbLZY4IXSeJxqIw=
86+
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
8787
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
8888
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
8989
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=

pkg/compose/create.go

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
154154
return ids, nil
155155
}
156156

157+
//nolint:gocyclo
157158
func (s *composeService) getCreateConfigs(ctx context.Context,
158159
p *types.Project,
159160
service types.ServiceConfig,
@@ -246,7 +247,10 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
246247
if err != nil {
247248
return createConfigs{}, err
248249
}
249-
networkMode, networkingConfig := defaultNetworkSettings(p, service, number, links, opts.UseNetworkAliases, apiVersion)
250+
networkMode, networkingConfig, err := defaultNetworkSettings(p, service, number, links, opts.UseNetworkAliases, apiVersion)
251+
if err != nil {
252+
return createConfigs{}, err
253+
}
250254
portBindings := buildContainerPortBindingOptions(service)
251255

252256
// MISC
@@ -356,7 +360,7 @@ func (s *composeService) prepareContainerMACAddress(ctx context.Context, service
356360
}
357361

358362
if len(withMacAddress) > 1 {
359-
return "", fmt.Errorf("a MAC address is specified for multiple networks (%s), but this feature requires Docker Engine 1.44 or later (currently: %s)", strings.Join(withMacAddress, ", "), version)
363+
return "", fmt.Errorf("a MAC address is specified for multiple networks (%s), but this feature requires Docker Engine v25 or later", strings.Join(withMacAddress, ", "))
360364
}
361365

362366
if mainNw != nil && mainNw.MacAddress != "" {
@@ -379,6 +383,8 @@ func getAliases(project *types.Project, service types.ServiceConfig, serviceInde
379383
}
380384

381385
func createEndpointSettings(p *types.Project, service types.ServiceConfig, serviceIndex int, networkKey string, links []string, useNetworkAliases bool) *network.EndpointSettings {
386+
const ifname = "com.docker.network.endpoint.ifname"
387+
382388
config := service.Networks[networkKey]
383389
var ipam *network.EndpointIPAMConfig
384390
var (
@@ -398,6 +404,15 @@ func createEndpointSettings(p *types.Project, service types.ServiceConfig, servi
398404
}
399405
macAddress = config.MacAddress
400406
driverOpts = config.DriverOpts
407+
if config.InterfaceName != "" {
408+
if driverOpts == nil {
409+
driverOpts = map[string]string{}
410+
}
411+
if name, ok := driverOpts[ifname]; ok && name != config.InterfaceName {
412+
logrus.Warnf("ignoring services.%s.networks.%s.interface_name as %s driver_opts is already declared", service.Name, networkKey, ifname)
413+
}
414+
driverOpts[ifname] = config.InterfaceName
415+
}
401416
gwPriority = config.GatewayPriority
402417
}
403418
return &network.EndpointSettings{
@@ -471,20 +486,17 @@ func (s *composeService) prepareLabels(labels types.Labels, service types.Servic
471486
}
472487

473488
// defaultNetworkSettings determines the container.NetworkMode and corresponding network.NetworkingConfig (nil if not applicable).
474-
func defaultNetworkSettings(
475-
project *types.Project,
476-
service types.ServiceConfig,
477-
serviceIndex int,
478-
links []string,
479-
useNetworkAliases bool,
489+
func defaultNetworkSettings(project *types.Project,
490+
service types.ServiceConfig, serviceIndex int,
491+
links []string, useNetworkAliases bool,
480492
version string,
481-
) (container.NetworkMode, *network.NetworkingConfig) {
493+
) (container.NetworkMode, *network.NetworkingConfig, error) {
482494
if service.NetworkMode != "" {
483-
return container.NetworkMode(service.NetworkMode), nil
495+
return container.NetworkMode(service.NetworkMode), nil, nil
484496
}
485497

486498
if len(project.Networks) == 0 {
487-
return "none", nil
499+
return "none", nil, nil
488500
}
489501

490502
var primaryNetworkKey string
@@ -515,6 +527,14 @@ func defaultNetworkSettings(
515527
}
516528
}
517529

530+
if versions.LessThan(version, "1.49") {
531+
for _, config := range service.Networks {
532+
if config != nil && config.InterfaceName != "" {
533+
return "", nil, fmt.Errorf("interface_name requires Docker Engine v28.1 or later")
534+
}
535+
}
536+
}
537+
518538
endpointsConfig[primaryNetworkMobyNetworkName] = primaryNetworkEndpoint
519539
networkConfig := &network.NetworkingConfig{
520540
EndpointsConfig: endpointsConfig,
@@ -523,7 +543,7 @@ func defaultNetworkSettings(
523543
// From the Engine API docs:
524544
// > Supported standard values are: bridge, host, none, and container:<name|id>.
525545
// > Any other value is taken as a custom network's name to which this container should connect to.
526-
return container.NetworkMode(primaryNetworkMobyNetworkName), networkConfig
546+
return container.NetworkMode(primaryNetworkMobyNetworkName), networkConfig, nil
527547
}
528548

529549
func getRestartPolicy(service types.ServiceConfig) container.RestartPolicy {

pkg/compose/create_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
219219
}),
220220
}
221221

222-
networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
222+
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
223+
assert.NilError(t, err)
223224
assert.Equal(t, string(networkMode), "myProject_myNetwork2")
224225
assert.Check(t, cmp.Len(networkConfig.EndpointsConfig, 1))
225226
assert.Check(t, cmp.Contains(networkConfig.EndpointsConfig, "myProject_myNetwork2"))
@@ -247,7 +248,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
247248
}),
248249
}
249250

250-
networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
251+
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
252+
assert.NilError(t, err)
251253
assert.Equal(t, string(networkMode), "myProject_default")
252254
assert.Check(t, cmp.Len(networkConfig.EndpointsConfig, 1))
253255
assert.Check(t, cmp.Contains(networkConfig.EndpointsConfig, "myProject_default"))
@@ -264,7 +266,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
264266
},
265267
}
266268

267-
networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
269+
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
270+
assert.NilError(t, err)
268271
assert.Equal(t, string(networkMode), "none")
269272
assert.Check(t, cmp.Nil(networkConfig))
270273
})
@@ -284,7 +287,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
284287
}),
285288
}
286289

287-
networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
290+
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
291+
assert.NilError(t, err)
288292
assert.Equal(t, string(networkMode), "host")
289293
assert.Check(t, cmp.Nil(networkConfig))
290294
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
test:
3+
image: alpine
4+
command: ip link show
5+
networks:
6+
default:
7+
interface_name: foobar

pkg/e2e/networks_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,21 @@ func TestMacAddress(t *testing.T) {
181181
res := c.RunDockerCmd(t, "inspect", fmt.Sprintf("%s-test-1", projectName), "-f", "{{ (index .NetworkSettings.Networks \"network_mac_address_default\" ).MacAddress }}")
182182
res.Assert(t, icmd.Expected{Out: "00:e0:84:35:d0:e8"})
183183
}
184+
185+
func TestInterfaceName(t *testing.T) {
186+
c := NewCLI(t)
187+
188+
version := c.RunDockerCmd(t, "version", "-f", "{{.Server.Version}}")
189+
major, _, found := strings.Cut(version.Combined(), ".")
190+
assert.Assert(t, found)
191+
if major == "26" || major == "27" {
192+
t.Skip("Skipping test due to docker version < 28")
193+
}
194+
195+
const projectName = "network_interface_name"
196+
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/network-interface-name/compose.yaml", "--project-name", projectName, "run", "test")
197+
t.Cleanup(func() {
198+
c.cleanupWithDown(t, projectName)
199+
})
200+
res.Assert(t, icmd.Expected{Out: "foobar@"})
201+
}

0 commit comments

Comments
 (0)