From 2e41476a5fe58ceae7b3523e5e27718c2c7590e6 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Wed, 12 Nov 2025 14:40:31 +0100 Subject: [PATCH 1/3] libnet: create DNS records on sbJoin (if not agent node) Commit a8b9eff90 removed a call to Network.updateSvcRecord from Network.createEndpoint on the grounds that: > all callers of Network.createEndpoint follow up with an Endpoint.Join, > which also sets up the DNS entry. However, the original call in Network.createEndpoint was gated by: ``` if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() { n.updateSvcRecord(context.WithoutCancel(ctx), ep, true) } ``` whereas the call in Endpoint.sbJoin() (invoked by Endpoint.Join()) is gated by: ``` if !n.getController().isAgent() { if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() { n.updateSvcRecord(context.WithoutCancel(ctx), ep, true) } } ``` As a result, once a node has joined a Swarm cluster, no DNS entries are created for non swarm-scoped networks. Change the condition used by `sbJoin` to match the original condition used in `createEndpoint`. Signed-off-by: Albin Kerouanton --- daemon/libnetwork/sandbox.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/daemon/libnetwork/sandbox.go b/daemon/libnetwork/sandbox.go index 4d0236f2e4..8f5e531188 100644 --- a/daemon/libnetwork/sandbox.go +++ b/daemon/libnetwork/sandbox.go @@ -348,10 +348,8 @@ func (sb *Sandbox) populateNetworkResources(ctx context.Context, ep *Endpoint) ( // Populate DNS records. n := ep.getNetwork() - if !n.getController().isAgent() { - if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() { - n.updateSvcRecord(context.WithoutCancel(ctx), ep, true) - } + if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() { + n.updateSvcRecord(context.WithoutCancel(ctx), ep, true) } if err := ep.addDriverInfoToCluster(); err != nil { From 47bd247d4dc0f2bb079f807660efad42d0eeaef3 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Wed, 12 Nov 2025 15:00:18 +0100 Subject: [PATCH 2/3] inte/networking: test DNS resolution for non swarm-scoped nws Previous commit reverted a faulty change that broke DNS resolution for non swarm-scoped networks once a node has joined a Swarm cluster. This commit adds an integration test to verify that we don't break DNS resolution again. Signed-off-by: Albin Kerouanton --- integration/networking/bridge_linux_test.go | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/integration/networking/bridge_linux_test.go b/integration/networking/bridge_linux_test.go index a4e291a993..09e9424ea4 100644 --- a/integration/networking/bridge_linux_test.go +++ b/integration/networking/bridge_linux_test.go @@ -2032,3 +2032,29 @@ func TestLegacyLinksEnvVars(t *testing.T) { }) } } + +// TestDNSNamesForNonSwarmScopedNetworks checks that container names can be resolved for non-swarm-scoped networks once +// a node has joined a Swarm cluster. +// +// Regression test for https://github.com/moby/moby/issues/51491. +func TestDNSNamesForNonSwarmScopedNetworks(t *testing.T) { + ctx := setupTest(t) + + d := daemon.New(t) + d.StartAndSwarmInit(ctx, t) + defer d.Stop(t) + + c := d.NewClientT(t) + defer c.Close() + + const bridgeName = "dnsnames-with-swarm" + network.CreateNoError(ctx, t, c, bridgeName) + defer network.RemoveNoError(ctx, t, c, bridgeName) + + res := container.RunAttach(ctx, t, c, + container.WithName("test"), + container.WithCmd("nslookup", "-type=a", "test."), + container.WithNetworkMode(bridgeName), + container.WithAutoRemove) + assert.Equal(t, res.ExitCode, 0, "exit code: %d, expected 0; stdout:\n%s", res.ExitCode, res.Stdout) +} From 53ea70ea462c39008901d2d29e294db4f7859406 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Thu, 13 Nov 2025 17:06:03 +0100 Subject: [PATCH 3/3] inte/networking: TestDisableIPv6OnInterface: add '-c1' to ping If the DNS name still resolves to an IP address, and that address is assigned to a running container, the ping command will run indefinitely and the test suite will time out for 10 mins. This is confusing, as it looks like a daemon hang, or a test suite hang, whereas it's just a test failure. Add '-c1' to ping to make it return immediately. Signed-off-by: Albin Kerouanton --- integration/networking/bridge_linux_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/networking/bridge_linux_test.go b/integration/networking/bridge_linux_test.go index 09e9424ea4..926b2bf9d7 100644 --- a/integration/networking/bridge_linux_test.go +++ b/integration/networking/bridge_linux_test.go @@ -1092,7 +1092,7 @@ func TestDisableIPv6OnInterface(t *testing.T) { // There should not be an IPv6 DNS or /etc/hosts entry. runRes := container.RunAttach(ctx, t, c, container.WithNetworkMode(tc.netName), - container.WithCmd("ping", "-6", ctrName), + container.WithCmd("ping", "-6", "-c1", ctrName), ) assert.Check(t, is.Equal(runRes.ExitCode, 1)) assert.Check(t, is.Contains(runRes.Stderr.String(), "bad address"))