Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/Microsoft/go-winio v0.6.2
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/buger/goterm v1.0.4
github.com/compose-spec/compose-go/v2 v2.6.1
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76
github.com/containerd/containerd/v2 v2.0.5
github.com/containerd/platforms v1.0.0-rc.1
github.com/davecgh/go-spew v1.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.6.1 h1:276YiQKRcGGtgkxiymzWHJ2CTv5joQA+7DTNrUA+rys=
github.com/compose-spec/compose-go/v2 v2.6.1/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76 h1:KZvD41eTRr9/n43zccAcGPBRgzHXdbLZY4IXSeJxqIw=
github.com/compose-spec/compose-go/v2 v2.6.2-0.20250423090706-30ff01d36f76/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
Expand Down
44 changes: 32 additions & 12 deletions pkg/compose/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
return ids, nil
}

//nolint:gocyclo
func (s *composeService) getCreateConfigs(ctx context.Context,
p *types.Project,
service types.ServiceConfig,
Expand Down Expand Up @@ -246,7 +247,10 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
if err != nil {
return createConfigs{}, err
}
networkMode, networkingConfig := defaultNetworkSettings(p, service, number, links, opts.UseNetworkAliases, apiVersion)
networkMode, networkingConfig, err := defaultNetworkSettings(p, service, number, links, opts.UseNetworkAliases, apiVersion)
if err != nil {
return createConfigs{}, err
}
portBindings := buildContainerPortBindingOptions(service)

// MISC
Expand Down Expand Up @@ -356,7 +360,7 @@ func (s *composeService) prepareContainerMACAddress(ctx context.Context, service
}

if len(withMacAddress) > 1 {
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)
return "", fmt.Errorf("a MAC address is specified for multiple networks (%s), but this feature requires Docker Engine v25 or later", strings.Join(withMacAddress, ", "))
}

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

func createEndpointSettings(p *types.Project, service types.ServiceConfig, serviceIndex int, networkKey string, links []string, useNetworkAliases bool) *network.EndpointSettings {
const ifname = "com.docker.network.endpoint.ifname"

config := service.Networks[networkKey]
var ipam *network.EndpointIPAMConfig
var (
Expand All @@ -398,6 +404,15 @@ func createEndpointSettings(p *types.Project, service types.ServiceConfig, servi
}
macAddress = config.MacAddress
driverOpts = config.DriverOpts
if config.InterfaceName != "" {
if driverOpts == nil {
driverOpts = map[string]string{}
}
if name, ok := driverOpts[ifname]; ok && name != config.InterfaceName {
logrus.Warnf("ignoring services.%s.networks.%s.interface_name as %s driver_opts is already declared", service.Name, networkKey, ifname)
}
driverOpts[ifname] = config.InterfaceName
}
gwPriority = config.GatewayPriority
}
return &network.EndpointSettings{
Expand Down Expand Up @@ -471,20 +486,17 @@ func (s *composeService) prepareLabels(labels types.Labels, service types.Servic
}

// defaultNetworkSettings determines the container.NetworkMode and corresponding network.NetworkingConfig (nil if not applicable).
func defaultNetworkSettings(
project *types.Project,
service types.ServiceConfig,
serviceIndex int,
links []string,
useNetworkAliases bool,
func defaultNetworkSettings(project *types.Project,
service types.ServiceConfig, serviceIndex int,
links []string, useNetworkAliases bool,
version string,
) (container.NetworkMode, *network.NetworkingConfig) {
) (container.NetworkMode, *network.NetworkingConfig, error) {
if service.NetworkMode != "" {
return container.NetworkMode(service.NetworkMode), nil
return container.NetworkMode(service.NetworkMode), nil, nil
}

if len(project.Networks) == 0 {
return "none", nil
return "none", nil, nil
}

var primaryNetworkKey string
Expand Down Expand Up @@ -515,6 +527,14 @@ func defaultNetworkSettings(
}
}

if versions.LessThan(version, "1.49") {
for _, config := range service.Networks {
if config != nil && config.InterfaceName != "" {
return "", nil, fmt.Errorf("interface_name requires Docker Engine v28.1 or later")
}
}
}

endpointsConfig[primaryNetworkMobyNetworkName] = primaryNetworkEndpoint
networkConfig := &network.NetworkingConfig{
EndpointsConfig: endpointsConfig,
Expand All @@ -523,7 +543,7 @@ func defaultNetworkSettings(
// From the Engine API docs:
// > Supported standard values are: bridge, host, none, and container:<name|id>.
// > Any other value is taken as a custom network's name to which this container should connect to.
return container.NetworkMode(primaryNetworkMobyNetworkName), networkConfig
return container.NetworkMode(primaryNetworkMobyNetworkName), networkConfig, nil
}

func getRestartPolicy(service types.ServiceConfig) container.RestartPolicy {
Expand Down
12 changes: 8 additions & 4 deletions pkg/compose/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
}),
}

networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
assert.NilError(t, err)
assert.Equal(t, string(networkMode), "myProject_myNetwork2")
assert.Check(t, cmp.Len(networkConfig.EndpointsConfig, 1))
assert.Check(t, cmp.Contains(networkConfig.EndpointsConfig, "myProject_myNetwork2"))
Expand Down Expand Up @@ -247,7 +248,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
}),
}

networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
assert.NilError(t, err)
assert.Equal(t, string(networkMode), "myProject_default")
assert.Check(t, cmp.Len(networkConfig.EndpointsConfig, 1))
assert.Check(t, cmp.Contains(networkConfig.EndpointsConfig, "myProject_default"))
Expand All @@ -264,7 +266,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
},
}

networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
assert.NilError(t, err)
assert.Equal(t, string(networkMode), "none")
assert.Check(t, cmp.Nil(networkConfig))
})
Expand All @@ -284,7 +287,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
}),
}

networkMode, networkConfig := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
networkMode, networkConfig, err := defaultNetworkSettings(&project, service, 1, nil, true, "1.43")
assert.NilError(t, err)
assert.Equal(t, string(networkMode), "host")
assert.Check(t, cmp.Nil(networkConfig))
})
Expand Down
7 changes: 7 additions & 0 deletions pkg/e2e/fixtures/network-interface-name/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
test:
image: alpine
command: ip link show
networks:
default:
interface_name: foobar
18 changes: 18 additions & 0 deletions pkg/e2e/networks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,21 @@ func TestMacAddress(t *testing.T) {
res := c.RunDockerCmd(t, "inspect", fmt.Sprintf("%s-test-1", projectName), "-f", "{{ (index .NetworkSettings.Networks \"network_mac_address_default\" ).MacAddress }}")
res.Assert(t, icmd.Expected{Out: "00:e0:84:35:d0:e8"})
}

func TestInterfaceName(t *testing.T) {
c := NewCLI(t)

version := c.RunDockerCmd(t, "version", "-f", "{{.Server.Version}}")
major, _, found := strings.Cut(version.Combined(), ".")
assert.Assert(t, found)
if major == "26" || major == "27" {
t.Skip("Skipping test due to docker version < 28")
}

const projectName = "network_interface_name"
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/network-interface-name/compose.yaml", "--project-name", projectName, "run", "test")
t.Cleanup(func() {
c.cleanupWithDown(t, projectName)
})
res.Assert(t, icmd.Expected{Out: "foobar@"})
}