diff --git a/Dockerfile.e2e b/Dockerfile.e2e
index 6ce92dd1fc..3d700fab51 100644
--- a/Dockerfile.e2e
+++ b/Dockerfile.e2e
@@ -55,15 +55,16 @@ RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash
 
 COPY contrib/httpserver/Dockerfile /tests/contrib/httpserver/Dockerfile
 COPY contrib/syscall-test /tests/contrib/syscall-test
-COPY hack/test/e2e-run.sh /run.sh
-COPY hack/make/.ensure-emptyfs /ensure-emptyfs.sh
 COPY integration-cli/fixtures /tests/integration-cli/fixtures
 
+COPY hack/test/e2e-run.sh /scripts/run.sh
+COPY hack/make/.ensure-emptyfs /scripts/ensure-emptyfs.sh
+
 COPY --from=builder /output/docker-frozen-images /docker-frozen-images
 COPY --from=builder /output/httpserver /tests/contrib/httpserver/httpserver
 COPY --from=builder /output/tests /tests
 COPY --from=builder /usr/local/bin/docker /usr/bin/docker
 
-ENV DOCKER_E2E=1 DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/
+ENV DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/
 
-ENTRYPOINT ["/run.sh"]
+ENTRYPOINT ["/scripts/run.sh"]
diff --git a/hack/test/e2e-run.sh b/hack/test/e2e-run.sh
index 0587148fb3..bfcc03f628 100755
--- a/hack/test/e2e-run.sh
+++ b/hack/test/e2e-run.sh
@@ -1,15 +1,41 @@
 #!/usr/bin/env bash
 set -e
 
+TESTFLAGS=${TESTFLAGS:-""}
+# Currently only DockerSuite and DockerNetworkSuite have been adapted for E2E testing
+TESTFLAGS_LEGACY=${TESTFLAGS_LEGACY:-""}
+TIMEOUT=${TIMEOUT:-60m}
+
+SCRIPTDIR="$(dirname ${BASH_SOURCE[0]})"
+
 export DOCKER_ENGINE_GOARCH=${DOCKER_ENGINE_GOARCH:-amd64}
 
-echo "Ensure emptyfs image is loaded"
-bash /ensure-emptyfs.sh
+run_test_integration() {
+  run_test_integration_suites
+  run_test_integration_legacy_suites
+}
 
-echo "Run integration/container tests"
-cd /tests/integration/container
-./test.main -test.v
+run_test_integration_suites() {
+  local flags="-test.v -test.timeout=${TIMEOUT} $TESTFLAGS"
+  for dir in /tests/integration/*; do
+    if ! (
+      cd $dir
+      echo "Running $PWD"
+      ./test.main $flags
+    ); then exit 1; fi
+  done
+}
 
-echo "Run integration-cli tests (DockerSuite, DockerNetworkSuite)"
-cd /tests/integration-cli
-./test.main -test.v -check.v -check.f "DockerSuite|DockerNetworkSuite"
+run_test_integration_legacy_suites() {
+  (
+    flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS_LEGACY"
+    cd /tests/integration-cli
+    echo "Running $PWD"
+    ./test.main $flags
+  )
+}
+
+bash $SCRIPTDIR/ensure-emptyfs.sh
+
+echo "Run integration tests"
+run_test_integration
diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go
index 3ee1a56245..2dfb696ab7 100644
--- a/integration-cli/check_test.go
+++ b/integration-cli/check_test.go
@@ -117,7 +117,7 @@ func (s *DockerRegistrySuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.reg = setupRegistry(c, false, "", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -151,7 +151,7 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64)
+	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64, SameHostDaemon)
 	s.reg = setupRegistry(c, true, "", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -185,7 +185,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.reg = setupRegistry(c, false, "htpasswd", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -221,7 +221,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
@@ -316,7 +316,7 @@ func (s *DockerSwarmSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerSwarmSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
 }
 
 func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Swarm {
@@ -468,7 +468,7 @@ func (ps *DockerPluginSuite) getPluginRepoWithTag() string {
 }
 
 func (ps *DockerPluginSuite) SetUpSuite(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, registry.Hosting)
 	ps.registry = setupRegistry(c, false, "", "")
 
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go
index dbec3dc76c..139a1b8ff8 100644
--- a/integration-cli/docker_api_containers_test.go
+++ b/integration-cli/docker_api_containers_test.go
@@ -1408,19 +1408,6 @@ func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs(
 	c.Assert(err.Error(), checker.Contains, "container rootfs is marked read-only")
 }
 
-func (s *DockerSuite) TestContainerAPIGetContainersJSONEmpty(c *check.C) {
-	// E2E: Test assumes no other containers running.
-	testRequires(c, NotE2E)
-
-	cli, err := client.NewEnvClient()
-	c.Assert(err, checker.IsNil)
-	defer cli.Close()
-
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
-	c.Assert(err, checker.IsNil)
-	c.Assert(containers, checker.HasLen, 0)
-}
-
 func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) {
 	// Not supported on Windows
 	testRequires(c, DaemonIsLinux)
diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go
index b9dae7aab7..fba69dc682 100644
--- a/integration-cli/docker_api_images_test.go
+++ b/integration-cli/docker_api_images_test.go
@@ -119,8 +119,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) {
 }
 
 func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) {
-	// E2E: Test runs local HTTP server.
-	testRequires(c, Network, NotE2E)
+	testRequires(c, Network, SameHostDaemon)
 
 	server := httptest.NewServer(http.NewServeMux())
 	defer server.Close()
diff --git a/integration-cli/docker_cli_authz_plugin_v2_test.go b/integration-cli/docker_cli_authz_plugin_v2_test.go
index bdc3f15e5b..30026f7fcd 100644
--- a/integration-cli/docker_cli_authz_plugin_v2_test.go
+++ b/integration-cli/docker_cli_authz_plugin_v2_test.go
@@ -30,7 +30,7 @@ type DockerAuthzV2Suite struct {
 }
 
 func (s *DockerAuthzV2Suite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, Network)
+	testRequires(c, DaemonIsLinux, Network, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
diff --git a/integration-cli/docker_cli_authz_unix_test.go b/integration-cli/docker_cli_authz_unix_test.go
index 5b7b9fab14..8a1bd023ea 100644
--- a/integration-cli/docker_cli_authz_unix_test.go
+++ b/integration-cli/docker_cli_authz_unix_test.go
@@ -64,6 +64,7 @@ type authorizationController struct {
 }
 
 func (s *DockerAuthzSuite) SetUpTest(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
diff --git a/integration-cli/docker_cli_build_unix_test.go b/integration-cli/docker_cli_build_unix_test.go
index 06c4d276e9..91a329fae8 100644
--- a/integration-cli/docker_cli_build_unix_test.go
+++ b/integration-cli/docker_cli_build_unix_test.go
@@ -25,20 +25,20 @@ import (
 )
 
 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
-	// E2E: Test assumes no other containers running.
-	testRequires(c, cpuCfsQuota, NotE2E)
+	testRequires(c, cpuCfsQuota)
 	name := "testbuildresourceconstraints"
+	buildLabel := "DockerSuite.TestBuildResourceConstraintsAreUsed"
 
 	ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(`
 	FROM hello-world:frozen
 	RUN ["/hello"]
 	`))
 	cli.Docker(
-		cli.Args("build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "--ulimit", "nofile=42", "-t", name, "."),
+		cli.Args("build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "--ulimit", "nofile=42", "--label="+buildLabel, "-t", name, "."),
 		cli.InDir(ctx.Dir),
 	).Assert(c, icmd.Success)
 
-	out := cli.DockerCmd(c, "ps", "-lq").Combined()
+	out := cli.DockerCmd(c, "ps", "-lq", "--filter", "label="+buildLabel).Combined()
 	cID := strings.TrimSpace(out)
 
 	type hostConfig struct {
diff --git a/integration-cli/docker_cli_config_ls_test.go b/integration-cli/docker_cli_config_ls_test.go
index 5c07012614..5f002bcab6 100644
--- a/integration-cli/docker_cli_config_ls_test.go
+++ b/integration-cli/docker_cli_config_ls_test.go
@@ -11,6 +11,7 @@ import (
 )
 
 func (s *DockerSwarmSuite) TestConfigList(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	d := s.AddDaemon(c, true, true)
 
 	testName0 := "test0"
diff --git a/integration-cli/docker_cli_external_volume_driver_unix_test.go b/integration-cli/docker_cli_external_volume_driver_unix_test.go
index 5fe417c2c8..2e2de972d5 100644
--- a/integration-cli/docker_cli_external_volume_driver_unix_test.go
+++ b/integration-cli/docker_cli_external_volume_driver_unix_test.go
@@ -50,6 +50,7 @@ type DockerExternalVolumeSuite struct {
 }
 
 func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go
index c9eef72326..4762e3993c 100644
--- a/integration-cli/docker_cli_network_unix_test.go
+++ b/integration-cli/docker_cli_network_unix_test.go
@@ -10,7 +10,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
-	"path/filepath"
 	"strings"
 	"time"
 
@@ -288,41 +287,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) {
 	}
 }
 
-func (s *DockerSuite) TestNetworkLsFormat(c *check.C) {
-	// E2E: Test assumes only default networks.
-	testRequires(c, DaemonIsLinux, NotE2E)
-	out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"bridge", "host", "none"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
-}
-
-func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) {
-	// E2E: Test assumes only default networks.
-	testRequires(c, DaemonIsLinux, NotE2E)
-
-	config := `{
-		"networksFormat": "{{ .Name }} default"
-}`
-	d, err := ioutil.TempDir("", "integration-cli-")
-	c.Assert(err, checker.IsNil)
-	defer os.RemoveAll(d)
-
-	err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
-	c.Assert(err, checker.IsNil)
-
-	out, _ := dockerCmd(c, "--config", d, "network", "ls")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"bridge default", "host default", "none default"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
-}
-
 func (s *DockerNetworkSuite) TestDockerNetworkCreatePredefined(c *check.C) {
 	predefined := []string{"bridge", "host", "none", "default"}
 	for _, net := range predefined {
@@ -353,8 +317,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
-	// E2E: Test assumes clean network environment.
-	testRequires(c, NotE2E)
+	testRequires(c, OnlyDefaultNetworks)
 	testNet := "testnet1"
 	testLabel := "foo"
 	testValue := "bar"
diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go
index 61241dd12c..12e7957bf3 100644
--- a/integration-cli/docker_cli_ps_test.go
+++ b/integration-cli/docker_cli_ps_test.go
@@ -519,9 +519,9 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) {
 }
 
 func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
-	// E2E: Test assumes no other containers.
 	// Problematic on Windows as it doesn't support links as of Jan 2016
-	testRequires(c, DaemonIsLinux, NotE2E)
+	testRequires(c, DaemonIsLinux)
+	existingContainers := ExistingContainerIDs(c)
 	runSleepingContainer(c, "--name=first")
 	runSleepingContainer(c, "--name=second", "--link=first:first")
 
@@ -529,6 +529,7 @@ func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
 	// strip header
 	lines = lines[1:]
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	expected := []string{"second", "first,second/first"}
 	var names []string
 	for _, l := range lines {
@@ -632,20 +633,6 @@ func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) {
 	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with names displayed twice: %v, got: %v", expected, names))
 }
 
-func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
-	// E2E: Test assumes no other containers.
-	testRequires(c, NotE2E)
-
-	// make sure no-container "docker ps" still prints the header row
-	out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
-	c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
-
-	// verify that "docker ps" with a container still prints the header row also
-	runSleepingContainer(c, "--name=test")
-	out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
-	c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
-}
-
 func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
 	existingContainers := ExistingContainerIDs(c)
 	config := `{
diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go
index 7f1cd8dd79..c3dfbcc9c5 100644
--- a/integration-cli/docker_cli_update_unix_test.go
+++ b/integration-cli/docker_cli_update_unix_test.go
@@ -14,6 +14,7 @@ import (
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/go-check/check"
 	"github.com/kr/pty"
 )
@@ -170,6 +171,18 @@ func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
 	c.Assert(strings.TrimSpace(out), checker.Equals, "314572800")
 }
 
+// GetKernelVersion gets the current kernel version.
+func GetKernelVersion() *kernel.VersionInfo {
+	v, _ := kernel.ParseRelease(testEnv.DaemonInfo.KernelVersion)
+	return v
+}
+
+// CheckKernelVersion checks if current kernel is newer than (or equal to)
+// the given version.
+func CheckKernelVersion(k, major, minor int) bool {
+	return kernel.CompareKernelVersion(*GetKernelVersion(), kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) > 0
+}
+
 func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, memoryLimitSupport)
diff --git a/integration-cli/docker_hub_pull_suite_test.go b/integration-cli/docker_hub_pull_suite_test.go
index 263372087c..286a3913ce 100644
--- a/integration-cli/docker_hub_pull_suite_test.go
+++ b/integration-cli/docker_hub_pull_suite_test.go
@@ -39,7 +39,7 @@ func newDockerHubPullSuite() *DockerHubPullSuite {
 
 // SetUpSuite starts the suite daemon.
 func (s *DockerHubPullSuite) SetUpSuite(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go
index c41a71fa29..411248195b 100644
--- a/integration-cli/requirements_test.go
+++ b/integration-cli/requirements_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"net/http"
@@ -10,6 +11,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/requirement"
 )
 
@@ -36,12 +39,16 @@ func DaemonIsLinux() bool {
 	return testEnv.DaemonInfo.OSType == "linux"
 }
 
-func E2E() bool {
-	return os.Getenv("DOCKER_E2E") != ""
-}
-
-func NotE2E() bool {
-	return !E2E()
+func OnlyDefaultNetworks() bool {
+	cli, err := client.NewEnvClient()
+	if err != nil {
+		return false
+	}
+	networks, err := cli.NetworkList(context.TODO(), types.NetworkListOptions{})
+	if err != nil || len(networks) > 0 {
+		return false
+	}
+	return true
 }
 
 // Deprecated: use skip.IfCondition(t, !testEnv.DaemonInfo.ExperimentalBuild)
diff --git a/integration-cli/utils_unix_test.go b/integration-cli/utils_unix_test.go
deleted file mode 100644
index b32e3baf3d..0000000000
--- a/integration-cli/utils_unix_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build linux freebsd solaris openbsd
-
-package main
-
-import (
-	"github.com/docker/docker/pkg/parsers/kernel"
-)
-
-// GetKernelVersion gets the current kernel version.
-func GetKernelVersion() *kernel.VersionInfo {
-	v, _ := kernel.ParseRelease(testEnv.DaemonInfo.KernelVersion)
-	return v
-}
-
-// CheckKernelVersion checks if current kernel is newer than (or equal to)
-// the given version.
-func CheckKernelVersion(k, major, minor int) bool {
-	return kernel.CompareKernelVersion(*GetKernelVersion(), kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) > 0
-}
diff --git a/integration/service/inspect_test.go b/integration/service/inspect_test.go
index 239075a0fd..61831b72f1 100644
--- a/integration/service/inspect_test.go
+++ b/integration/service/inspect_test.go
@@ -12,12 +12,14 @@ import (
 	"github.com/docker/docker/integration-cli/daemon"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/gotestyourself/gotestyourself/poll"
+	"github.com/gotestyourself/gotestyourself/skip"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"golang.org/x/net/context"
 )
 
 func TestInspect(t *testing.T) {
+	skip.IfCondition(t, !testEnv.IsLocalDaemon())
 	defer setupTest(t)()
 	d := newSwarm(t)
 	defer d.Stop(t)