Browse code

Remove/replace integration-cli tests that use iptables directly

In preparation for testing with an nftables backend.

Signed-off-by: Rob Murray <rob.murray@docker.com>

Rob Murray authored on 2025/04/10 03:18:18
Showing 4 changed files
... ...
@@ -30,7 +30,6 @@ import (
30 30
 	"github.com/docker/docker/integration-cli/cli"
31 31
 	"github.com/docker/docker/integration-cli/cli/build"
32 32
 	"github.com/docker/docker/integration-cli/daemon"
33
-	"github.com/docker/docker/libnetwork/drivers/bridge"
34 33
 	"github.com/docker/docker/opts"
35 34
 	"github.com/docker/docker/testutil"
36 35
 	testdaemon "github.com/docker/docker/testutil/daemon"
... ...
@@ -222,66 +221,6 @@ func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *testing
222 222
 	}
223 223
 }
224 224
 
225
-func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *testing.T) {
226
-	s.d.StartWithBusybox(testutil.GetContext(c), c)
227
-
228
-	if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
229
-		c.Fatalf("Could not run top: %s, %v", out, err)
230
-	}
231
-
232
-	ipTablesSearchString := "tcp dpt:80"
233
-
234
-	// get output from iptables with container running
235
-	verifyIPTablesContains(c, ipTablesSearchString)
236
-
237
-	s.d.Stop(c)
238
-
239
-	// get output from iptables after restart
240
-	verifyIPTablesDoesNotContains(c, ipTablesSearchString)
241
-}
242
-
243
-func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *testing.T) {
244
-	s.d.StartWithBusybox(testutil.GetContext(c), c)
245
-
246
-	if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil {
247
-		c.Fatalf("Could not run top: %s, %v", out, err)
248
-	}
249
-
250
-	// get output from iptables with container running
251
-	ipTablesSearchString := "tcp dpt:80"
252
-	verifyIPTablesContains(c, ipTablesSearchString)
253
-
254
-	s.d.Restart(c)
255
-
256
-	// make sure the container is not running
257
-	runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top")
258
-	if err != nil {
259
-		c.Fatalf("Could not inspect on container: %s, %v", runningOut, err)
260
-	}
261
-	if strings.TrimSpace(runningOut) != "true" {
262
-		c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut))
263
-	}
264
-
265
-	// get output from iptables after restart
266
-	verifyIPTablesContains(c, ipTablesSearchString)
267
-}
268
-
269
-func verifyIPTablesContains(c *testing.T, ipTablesSearchString string) {
270
-	result := icmd.RunCommand("iptables", "-nvL")
271
-	result.Assert(c, icmd.Success)
272
-	if !strings.Contains(result.Combined(), ipTablesSearchString) {
273
-		c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, result.Combined())
274
-	}
275
-}
276
-
277
-func verifyIPTablesDoesNotContains(c *testing.T, ipTablesSearchString string) {
278
-	result := icmd.RunCommand("iptables", "-nvL")
279
-	result.Assert(c, icmd.Success)
280
-	if strings.Contains(result.Combined(), ipTablesSearchString) {
281
-		c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, result.Combined())
282
-	}
283
-}
284
-
285 225
 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR
286 226
 // that running containers are given a link-local and global IPv6 address
287 227
 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *testing.T) {
... ...
@@ -421,38 +360,6 @@ func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *testing.T) {
421 421
 	}
422 422
 }
423 423
 
424
-func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *testing.T) {
425
-	d := s.d
426
-	err := d.StartWithError("--bridge", "nosuchbridge")
427
-	assert.ErrorContains(c, err, "", `--bridge option with an invalid bridge should cause the daemon to fail`)
428
-	defer d.Restart(c)
429
-
430
-	// make sure the default docker0 bridge doesn't interfere with the test,
431
-	// which may happen if it was created with the same IP range.
432
-	deleteInterface(c, "docker0")
433
-
434
-	bridgeName := "ext-bridge1"
435
-	bridgeIP := "192.169.1.1/24"
436
-	_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
437
-
438
-	createInterface(c, "bridge", bridgeName, bridgeIP)
439
-	defer deleteInterface(c, bridgeName)
440
-
441
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName)
442
-
443
-	ipTablesSearchString := bridgeIPNet.String()
444
-	icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
445
-		Out: ipTablesSearchString,
446
-	})
447
-
448
-	out, err := d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top")
449
-	assert.NilError(c, err, out)
450
-
451
-	containerIP := d.FindContainerIP(c, "ExtContainer")
452
-	ip := net.ParseIP(containerIP)
453
-	assert.Assert(c, bridgeIPNet.Contains(ip), "Container IP-Address must be in the same subnet range : %s", containerIP)
454
-}
455
-
456 424
 func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *testing.T) {
457 425
 	// start with bridge none
458 426
 	d := s.d
... ...
@@ -483,317 +390,6 @@ func deleteInterface(c *testing.T, ifName string) {
483 483
 	icmd.RunCommand("iptables", "--flush").Assert(c, icmd.Success)
484 484
 }
485 485
 
486
-func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *testing.T) {
487
-	// TestDaemonBridgeIP Steps
488
-	// 1. Delete the existing docker0 Bridge
489
-	// 2. Set --bip daemon configuration and start the new Docker Daemon
490
-	// 3. Check if the bip config has taken effect using ifconfig and iptables commands
491
-	// 4. Launch a Container and make sure the IP-Address is in the expected subnet
492
-	// 5. Delete the docker0 Bridge
493
-	// 6. Restart the Docker Daemon (via deferred action)
494
-	//    This Restart takes care of bringing docker0 interface back to auto-assigned IP
495
-
496
-	defaultNetworkBridge := "docker0"
497
-	deleteInterface(c, defaultNetworkBridge)
498
-
499
-	d := s.d
500
-
501
-	bridgeIP := "192.169.1.1/24"
502
-	ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
503
-
504
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIP)
505
-	defer d.Restart(c)
506
-
507
-	ifconfigSearchString := ip.String()
508
-	icmd.RunCommand("ifconfig", defaultNetworkBridge).Assert(c, icmd.Expected{
509
-		Out: ifconfigSearchString,
510
-	})
511
-
512
-	ipTablesSearchString := bridgeIPNet.String()
513
-	icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
514
-		Out: ipTablesSearchString,
515
-	})
516
-
517
-	out, err := d.Cmd("run", "-d", "--name", "test", "busybox", "top")
518
-	assert.NilError(c, err, out)
519
-
520
-	containerIP := d.FindContainerIP(c, "test")
521
-	ip = net.ParseIP(containerIP)
522
-	assert.Equal(c, bridgeIPNet.Contains(ip), true, fmt.Sprintf("Container IP-Address must be in the same subnet range : %s", containerIP))
523
-	deleteInterface(c, defaultNetworkBridge)
524
-}
525
-
526
-func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *testing.T) {
527
-	s.d.Start(c)
528
-	defer s.d.Restart(c)
529
-	s.d.Stop(c)
530
-
531
-	// now we will change the docker0's IP and then try starting the daemon
532
-	bridgeIP := "192.169.100.1/24"
533
-	_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
534
-
535
-	icmd.RunCommand("ifconfig", "docker0", bridgeIP).Assert(c, icmd.Success)
536
-
537
-	s.d.Start(c, "--bip", bridgeIP)
538
-
539
-	// check if the iptables contains new bridgeIP MASQUERADE rule
540
-	ipTablesSearchString := bridgeIPNet.String()
541
-	icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
542
-		Out: ipTablesSearchString,
543
-	})
544
-}
545
-
546
-func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *testing.T) {
547
-	d := s.d
548
-
549
-	// make sure the default docker0 bridge doesn't interfere with the test,
550
-	// which may happen if it was created with the same IP range.
551
-	deleteInterface(c, "docker0")
552
-
553
-	bridgeName := "ext-bridge2"
554
-	bridgeIP := "192.169.1.1/24"
555
-
556
-	createInterface(c, "bridge", bridgeName, bridgeIP)
557
-	defer deleteInterface(c, bridgeName)
558
-
559
-	args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"}
560
-	d.StartWithBusybox(testutil.GetContext(c), c, args...)
561
-	defer d.Restart(c)
562
-
563
-	for i := 0; i < 4; i++ {
564
-		cName := "Container" + strconv.Itoa(i)
565
-		out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
566
-		if err != nil {
567
-			assert.Assert(c, strings.Contains(out, "no available IPv4 addresses"), "Could not run a Container : %s %s", err.Error(), out)
568
-		}
569
-	}
570
-}
571
-
572
-func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *testing.T) {
573
-	d := s.d
574
-
575
-	// make sure the default docker0 bridge doesn't interfere with the test,
576
-	// which may happen if it was created with the same IP range.
577
-	deleteInterface(c, "docker0")
578
-
579
-	bridgeName := "ext-bridge3"
580
-	bridgeIP := "10.2.2.1/16"
581
-
582
-	createInterface(c, "bridge", bridgeName, bridgeIP)
583
-	defer deleteInterface(c, bridgeName)
584
-
585
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24")
586
-	defer s.d.Restart(c)
587
-
588
-	out, err := d.Cmd("run", "-d", "--name", "bb", "busybox", "top")
589
-	assert.NilError(c, err, out)
590
-	defer d.Cmd("stop", "bb")
591
-
592
-	out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'")
593
-	assert.NilError(c, err)
594
-	assert.Equal(c, out, "10.2.2.0\n")
595
-
596
-	out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'")
597
-	assert.NilError(c, err, out)
598
-	assert.Equal(c, out, "10.2.2.2\n")
599
-}
600
-
601
-func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *testing.T) {
602
-	d := s.d
603
-
604
-	// make sure the default docker0 bridge doesn't interfere with the test,
605
-	// which may happen if it was created with the same IP range.
606
-	deleteInterface(c, "docker0")
607
-
608
-	bridgeName := "ext-bridge4"
609
-	bridgeIP := "172.27.42.1/16"
610
-
611
-	createInterface(c, "bridge", bridgeName, bridgeIP)
612
-	defer deleteInterface(c, bridgeName)
613
-
614
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP)
615
-	defer s.d.Restart(c)
616
-
617
-	out, err := d.Cmd("run", "-d", "busybox", "top")
618
-	assert.NilError(c, err, out)
619
-	cid1 := strings.TrimSpace(out)
620
-	defer d.Cmd("stop", cid1)
621
-}
622
-
623
-func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *testing.T) {
624
-	defaultNetworkBridge := "docker0"
625
-	deleteInterface(c, defaultNetworkBridge)
626
-
627
-	d := s.d
628
-
629
-	bridgeIP := "192.169.1.1"
630
-	bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP)
631
-
632
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIPNet)
633
-	defer d.Restart(c)
634
-
635
-	expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP)
636
-	out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
637
-	assert.NilError(c, err, out)
638
-	assert.Equal(c, strings.Contains(out, expectedMessage), true, fmt.Sprintf("Implicit default gateway should be bridge IP %s, but default route was '%s'", bridgeIP, strings.TrimSpace(out)))
639
-	deleteInterface(c, defaultNetworkBridge)
640
-}
641
-
642
-func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *testing.T) {
643
-	defaultNetworkBridge := "docker0"
644
-	deleteInterface(c, defaultNetworkBridge)
645
-
646
-	d := s.d
647
-
648
-	bridgeIP := "192.169.1.1"
649
-	bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP)
650
-	gatewayIP := "192.169.1.254"
651
-
652
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIPNet, "--default-gateway", gatewayIP)
653
-	defer d.Restart(c)
654
-
655
-	expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP)
656
-	out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
657
-	assert.NilError(c, err, out)
658
-	assert.Equal(c, strings.Contains(out, expectedMessage), true, fmt.Sprintf("Explicit default gateway should be %s, but default route was '%s'", gatewayIP, strings.TrimSpace(out)))
659
-	deleteInterface(c, defaultNetworkBridge)
660
-}
661
-
662
-func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *testing.T) {
663
-	defaultNetworkBridge := "docker0"
664
-	deleteInterface(c, defaultNetworkBridge)
665
-
666
-	// Program a custom default gateway outside of the container subnet, daemon should accept it and start
667
-	s.d.StartWithBusybox(testutil.GetContext(c), c, "--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254")
668
-
669
-	deleteInterface(c, defaultNetworkBridge)
670
-	s.d.Restart(c)
671
-}
672
-
673
-func (s *DockerDaemonSuite) TestDaemonIP(c *testing.T) {
674
-	d := s.d
675
-
676
-	// make sure the default docker0 bridge doesn't interfere with the test,
677
-	// which may happen if it was created with the same IP range.
678
-	deleteInterface(c, "docker0")
679
-
680
-	ipStr := "192.170.1.1/24"
681
-	ip, _, _ := net.ParseCIDR(ipStr)
682
-	args := []string{"--ip", ip.String()}
683
-	d.StartWithBusybox(testutil.GetContext(c), c, args...)
684
-	defer d.Restart(c)
685
-
686
-	out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
687
-	assert.Assert(c, err != nil, "Running a container must fail with an invalid --ip option")
688
-	assert.Check(c, is.Contains(out, "failed to bind host port for 192.170.1.1"))
689
-
690
-	ifName := "dummy"
691
-	createInterface(c, "dummy", ifName, ipStr)
692
-	defer deleteInterface(c, ifName)
693
-
694
-	_, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
695
-	assert.NilError(c, err, out)
696
-
697
-	result := icmd.RunCommand("iptables", "-t", "nat", "-nvL")
698
-	result.Assert(c, icmd.Success)
699
-	regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String())
700
-	matched, _ := regexp.MatchString(regex, result.Combined())
701
-	assert.Equal(c, matched, true, fmt.Sprintf("iptables output should have contained %q, but was %q", regex, result.Combined()))
702
-}
703
-
704
-func (s *DockerDaemonSuite) TestDaemonICCPing(c *testing.T) {
705
-	testRequires(c, bridgeNfIptables)
706
-	d := s.d
707
-
708
-	// make sure the default docker0 bridge doesn't interfere with the test,
709
-	// which may happen if it was created with the same IP range.
710
-	deleteInterface(c, "docker0")
711
-
712
-	const bridgeName = "ext-bridge5"
713
-	const bridgeIP = "192.169.1.1/24"
714
-
715
-	createInterface(c, "bridge", bridgeName, bridgeIP)
716
-	defer deleteInterface(c, bridgeName)
717
-
718
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--icc=false")
719
-	defer d.Restart(c)
720
-
721
-	result := icmd.RunCommand("sh", "-c", "iptables -vL "+bridge.DockerForwardChain+" | grep DROP")
722
-	result.Assert(c, icmd.Success)
723
-
724
-	// strip whitespace and newlines to verify we only found a single DROP
725
-	out := strings.TrimSpace(result.Stdout())
726
-	assert.Assert(c, is.Equal(strings.Count(out, "\n"), 0), "only expected a single DROP rules")
727
-
728
-	// Column headers are stripped because of grep-ing, but should be:
729
-	//
730
-	//    pkts bytes target     prot opt in          out          source    destination
731
-	//       0     0 DROP       all  --  ext-bridge5 ext-bridge5  anywhere  anywhere
732
-	//
733
-	//nolint:dupword
734
-	cols := strings.Fields(out)
735
-
736
-	expected := []string{"0", "0", "DROP", "all", "--", bridgeName, bridgeName, "anywhere", "anywhere"}
737
-	assert.DeepEqual(c, cols, expected)
738
-
739
-	// Pinging another container must fail with --icc=false
740
-	pingContainers(c, d, true)
741
-
742
-	const cidr = "192.171.1.1/24"
743
-	ip, _, _ := net.ParseCIDR(cidr)
744
-	const ifName = "icc-dummy"
745
-
746
-	createInterface(c, "dummy", ifName, cidr)
747
-	defer deleteInterface(c, ifName)
748
-
749
-	// But, Pinging external or a Host interface must succeed
750
-	pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String())
751
-	runArgs := []string{"run", "--rm", "busybox", "sh", "-c", pingCmd}
752
-	out, err := d.Cmd(runArgs...)
753
-	assert.NilError(c, err, out)
754
-}
755
-
756
-func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *testing.T) {
757
-	d := s.d
758
-
759
-	// make sure the default docker0 bridge doesn't interfere with the test,
760
-	// which may happen if it was created with the same IP range.
761
-	deleteInterface(c, "docker0")
762
-
763
-	const bridgeName = "ext-bridge6"
764
-	const bridgeIP = "192.169.1.1/24"
765
-
766
-	createInterface(c, "bridge", bridgeName, bridgeIP)
767
-	defer deleteInterface(c, bridgeName)
768
-
769
-	d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--icc=false")
770
-	defer d.Restart(c)
771
-
772
-	result := icmd.RunCommand("sh", "-c", "iptables -vL "+bridge.DockerForwardChain+" | grep DROP")
773
-	result.Assert(c, icmd.Success)
774
-
775
-	// strip whitespace and newlines to verify we only found a single DROP
776
-	out := strings.TrimSpace(result.Stdout())
777
-	assert.Assert(c, is.Equal(strings.Count(out, "\n"), 0), "only expected a single DROP rules")
778
-
779
-	// Column headers are stripped because of grep-ing, but should be:
780
-	//
781
-	//    pkts bytes target     prot opt in          out          source    destination
782
-	//       0     0 DROP       all  --  ext-bridge6 ext-bridge6  anywhere  anywhere
783
-	//
784
-	//nolint:dupword
785
-	cols := strings.Fields(out)
786
-
787
-	expected := []string{"0", "0", "DROP", "all", "--", bridgeName, bridgeName, "anywhere", "anywhere"}
788
-	assert.DeepEqual(c, cols, expected)
789
-
790
-	out, err := d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567")
791
-	assert.NilError(c, err, out)
792
-
793
-	out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567")
794
-	assert.NilError(c, err, out)
795
-}
796
-
797 486
 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *testing.T) {
798 487
 	s.d.StartWithBusybox(testutil.GetContext(c), c, "--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024")
799 488
 
... ...
@@ -1170,30 +766,6 @@ func (s *DockerDaemonSuite) TestHTTPSInfoRogueServerCert(c *testing.T) {
1170 1170
 	}
1171 1171
 }
1172 1172
 
1173
-func pingContainers(c *testing.T, d *daemon.Daemon, expectFailure bool) {
1174
-	var dargs []string
1175
-	if d != nil {
1176
-		dargs = []string{"--host", d.Sock()}
1177
-	}
1178
-
1179
-	args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top")
1180
-	cli.DockerCmd(c, args...)
1181
-
1182
-	args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c")
1183
-	pingCmd := "ping -c 1 %s -W 1"
1184
-	args = append(args, fmt.Sprintf(pingCmd, "alias1"))
1185
-	_, _, err := dockerCmdWithError(args...)
1186
-
1187
-	if expectFailure {
1188
-		assert.ErrorContains(c, err, "")
1189
-	} else {
1190
-		assert.NilError(c, err)
1191
-	}
1192
-
1193
-	args = append(dargs, "rm", "-f", "container1")
1194
-	cli.DockerCmd(c, args...)
1195
-}
1196
-
1197 1173
 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *testing.T) {
1198 1174
 	s.d.StartWithBusybox(testutil.GetContext(c), c)
1199 1175
 
... ...
@@ -2018,22 +2018,6 @@ func (s *DockerCLIRunSuite) TestRunWithInvalidMacAddress(c *testing.T) {
2018 2018
 	}
2019 2019
 }
2020 2020
 
2021
-func (s *DockerCLIRunSuite) TestRunDeallocatePortOnMissingIptablesRule(c *testing.T) {
2022
-	// TODO Windows. Network settings are not propagated back to inspect.
2023
-	testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux)
2024
-
2025
-	out := cli.DockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top").Combined()
2026
-
2027
-	id := strings.TrimSpace(out)
2028
-	ip := inspectField(c, id, "NetworkSettings.Networks.bridge.IPAddress")
2029
-	icmd.RunCommand("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip),
2030
-		"!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT").Assert(c, icmd.Success)
2031
-
2032
-	cli.DockerCmd(c, "rm", "-fv", id)
2033
-
2034
-	cli.DockerCmd(c, "run", "-d", "-p", "23:23", "busybox", "top")
2035
-}
2036
-
2037 2021
 func (s *DockerCLIRunSuite) TestRunPortInUse(c *testing.T) {
2038 2022
 	// TODO Windows. The duplicate NAT message returned by Windows will be
2039 2023
 	// changing as is currently completely undecipherable. Does need modifying
... ...
@@ -64,11 +64,6 @@ func seccompEnabled() bool {
64 64
 	return sysInfo.Seccomp
65 65
 }
66 66
 
67
-func bridgeNfIptables() bool {
68
-	content, err := os.ReadFile("/proc/sys/net/bridge/bridge-nf-call-iptables")
69
-	return err == nil && strings.TrimSpace(string(content)) == "1"
70
-}
71
-
72 67
 func onlyCgroupsv2() bool {
73 68
 	// Only check for unified, cgroup v1 tests can run under other modes
74 69
 	return cgroups.Mode() == cgroups.Unified
... ...
@@ -3,6 +3,7 @@ package bridge
3 3
 import (
4 4
 	"context"
5 5
 	"fmt"
6
+	"net"
6 7
 	"net/netip"
7 8
 	"strings"
8 9
 	"testing"
... ...
@@ -754,3 +755,59 @@ func TestRemoveLegacyLink(t *testing.T) {
754 754
 	res = ctr.ExecT(ctx, t, c, clientId, []string{"wget", "-T3", "http://" + svrAddr})
755 755
 	assert.Check(t, is.Contains(res.Stderr(), "download timed out"))
756 756
 }
757
+
758
+// TestPortMappingRestore check that port mappings are restored when a container
759
+// is restarted after a daemon restart.
760
+//
761
+// Replacement for integration-cli test DockerDaemonSuite/TestDaemonIptablesCreate
762
+func TestPortMappingRestore(t *testing.T) {
763
+	skip.If(t, testEnv.IsRootless(), "fails before and after restart")
764
+
765
+	ctx := setupTest(t)
766
+	d := daemon.New(t)
767
+	d.StartWithBusybox(ctx, t)
768
+	defer d.Stop(t)
769
+	c := d.NewClientT(t)
770
+
771
+	const svrName = "svr"
772
+	cid := ctr.Run(ctx, t, c,
773
+		ctr.WithExposedPorts("80/tcp"),
774
+		ctr.WithPortMap(nat.PortMap{"80/tcp": {}}),
775
+		ctr.WithName(svrName),
776
+		ctr.WithRestartPolicy(containertypes.RestartPolicyUnlessStopped),
777
+		ctr.WithCmd("httpd", "-f"),
778
+	)
779
+	defer func() { ctr.Remove(ctx, t, c, cid, containertypes.RemoveOptions{Force: true}) }()
780
+
781
+	check := func() {
782
+		t.Helper()
783
+		insp := ctr.Inspect(ctx, t, c, cid)
784
+		assert.Check(t, is.Equal(insp.State.Running, true))
785
+		if assert.Check(t, is.Contains(insp.NetworkSettings.Ports, nat.Port("80/tcp"))) &&
786
+			assert.Check(t, is.Len(insp.NetworkSettings.Ports["80/tcp"], 2)) {
787
+			hostPort := insp.NetworkSettings.Ports["80/tcp"][0].HostPort
788
+			res := ctr.RunAttach(ctx, t, c,
789
+				ctr.WithExtraHost("thehost:host-gateway"),
790
+				ctr.WithCmd("wget", "-T3", "http://"+net.JoinHostPort("thehost", hostPort)),
791
+			)
792
+			// 404 means the http request worked, but the http server had nothing to serve.
793
+			assert.Check(t, is.Contains(res.Stderr.String(), "404 Not Found"))
794
+		}
795
+	}
796
+
797
+	check()
798
+	d.Restart(t)
799
+	check()
800
+}
801
+
802
+// TestNoSuchExternalBridge checks that the daemon won't start if it's given a "--bridge"
803
+// that doesn't exist.
804
+//
805
+// Replacement for part of DockerDaemonSuite/TestDaemonBridgeExternal
806
+func TestNoSuchExternalBridge(t *testing.T) {
807
+	_ = setupTest(t)
808
+	d := daemon.New(t)
809
+	defer d.Stop(t)
810
+	err := d.StartWithError("--bridge", "nosuchbridge")
811
+	assert.Check(t, err != nil, "Expected daemon startup to fail")
812
+}