run_cgroupns_linux_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package container // import "github.com/docker/docker/integration/container"
  2. import (
  3. "context"
  4. "testing"
  5. "github.com/docker/docker/client"
  6. "github.com/docker/docker/integration/internal/container"
  7. "github.com/docker/docker/integration/internal/requirement"
  8. "github.com/docker/docker/testutil"
  9. "github.com/docker/docker/testutil/daemon"
  10. "gotest.tools/v3/assert"
  11. "gotest.tools/v3/skip"
  12. )
  13. // Bring up a daemon with the specified default cgroup namespace mode, and then create a container with the container options
  14. func testRunWithCgroupNs(ctx context.Context, t *testing.T, daemonNsMode string, containerOpts ...func(*container.TestContainerConfig)) (string, string) {
  15. d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode))
  16. apiClient := d.NewClientT(t)
  17. d.StartWithBusybox(ctx, t)
  18. defer d.Stop(t)
  19. cID := container.Run(ctx, t, apiClient, containerOpts...)
  20. daemonCgroup := d.CgroupNamespace(t)
  21. containerCgroup := container.GetContainerNS(ctx, t, apiClient, cID, "cgroup")
  22. return containerCgroup, daemonCgroup
  23. }
  24. // Bring up a daemon with the specified default cgroup namespace mode. Create a container with the container options,
  25. // expecting an error with the specified string
  26. func testCreateFailureWithCgroupNs(ctx context.Context, t *testing.T, daemonNsMode string, errStr string, containerOpts ...func(*container.TestContainerConfig)) {
  27. d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode))
  28. apiClient := d.NewClientT(t)
  29. d.StartWithBusybox(ctx, t)
  30. defer d.Stop(t)
  31. _, err := container.CreateFromConfig(ctx, apiClient, container.NewTestConfig(containerOpts...))
  32. assert.ErrorContains(t, err, errStr)
  33. }
  34. func TestCgroupNamespacesRun(t *testing.T) {
  35. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  36. skip.If(t, testEnv.IsRemoteDaemon())
  37. skip.If(t, !requirement.CgroupNamespacesEnabled())
  38. ctx := testutil.StartSpan(baseContext, t)
  39. // When the daemon defaults to private cgroup namespaces, containers launched
  40. // should be in their own private cgroup namespace by default
  41. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private")
  42. assert.Assert(t, daemonCgroup != containerCgroup)
  43. }
  44. func TestCgroupNamespacesRunPrivileged(t *testing.T) {
  45. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  46. skip.If(t, testEnv.IsRemoteDaemon())
  47. skip.If(t, !requirement.CgroupNamespacesEnabled())
  48. skip.If(t, testEnv.DaemonInfo.CgroupVersion == "2", "on cgroup v2, privileged containers use private cgroupns")
  49. ctx := testutil.StartSpan(baseContext, t)
  50. // When the daemon defaults to private cgroup namespaces, privileged containers
  51. // launched should not be inside their own cgroup namespaces
  52. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithPrivileged(true))
  53. assert.Assert(t, daemonCgroup == containerCgroup)
  54. }
  55. func TestCgroupNamespacesRunDaemonHostMode(t *testing.T) {
  56. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  57. skip.If(t, testEnv.IsRemoteDaemon())
  58. skip.If(t, !requirement.CgroupNamespacesEnabled())
  59. ctx := testutil.StartSpan(baseContext, t)
  60. // When the daemon defaults to host cgroup namespaces, containers
  61. // launched should not be inside their own cgroup namespaces
  62. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "host")
  63. assert.Assert(t, daemonCgroup == containerCgroup)
  64. }
  65. func TestCgroupNamespacesRunHostMode(t *testing.T) {
  66. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  67. skip.If(t, testEnv.IsRemoteDaemon())
  68. skip.If(t, !requirement.CgroupNamespacesEnabled())
  69. ctx := testutil.StartSpan(baseContext, t)
  70. // When the daemon defaults to private cgroup namespaces, containers launched
  71. // with a cgroup ns mode of "host" should not be inside their own cgroup namespaces
  72. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithCgroupnsMode("host"))
  73. assert.Assert(t, daemonCgroup == containerCgroup)
  74. }
  75. func TestCgroupNamespacesRunPrivateMode(t *testing.T) {
  76. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  77. skip.If(t, testEnv.IsRemoteDaemon())
  78. skip.If(t, !requirement.CgroupNamespacesEnabled())
  79. ctx := testutil.StartSpan(baseContext, t)
  80. // When the daemon defaults to private cgroup namespaces, containers launched
  81. // with a cgroup ns mode of "private" should be inside their own cgroup namespaces
  82. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithCgroupnsMode("private"))
  83. assert.Assert(t, daemonCgroup != containerCgroup)
  84. }
  85. func TestCgroupNamespacesRunPrivilegedAndPrivate(t *testing.T) {
  86. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  87. skip.If(t, testEnv.IsRemoteDaemon())
  88. skip.If(t, !requirement.CgroupNamespacesEnabled())
  89. ctx := testutil.StartSpan(baseContext, t)
  90. containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithPrivileged(true), container.WithCgroupnsMode("private"))
  91. assert.Assert(t, daemonCgroup != containerCgroup)
  92. }
  93. func TestCgroupNamespacesRunInvalidMode(t *testing.T) {
  94. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  95. skip.If(t, testEnv.IsRemoteDaemon())
  96. skip.If(t, !requirement.CgroupNamespacesEnabled())
  97. ctx := testutil.StartSpan(baseContext, t)
  98. // An invalid cgroup namespace mode should return an error on container creation
  99. errStr := "invalid cgroup namespace mode: invalid"
  100. testCreateFailureWithCgroupNs(ctx, t, "private", errStr, container.WithCgroupnsMode("invalid"))
  101. }
  102. // Clients before 1.40 expect containers to be created in the host cgroup namespace,
  103. // regardless of the default setting of the daemon, unless running with cgroup v2
  104. func TestCgroupNamespacesRunOlderClient(t *testing.T) {
  105. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  106. skip.If(t, testEnv.IsRemoteDaemon())
  107. skip.If(t, !requirement.CgroupNamespacesEnabled())
  108. ctx := testutil.StartSpan(baseContext, t)
  109. d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode("private"))
  110. apiClient := d.NewClientT(t, client.WithVersion("1.39"))
  111. d.StartWithBusybox(ctx, t)
  112. defer d.Stop(t)
  113. cID := container.Run(ctx, t, apiClient)
  114. daemonCgroup := d.CgroupNamespace(t)
  115. containerCgroup := container.GetContainerNS(ctx, t, apiClient, cID, "cgroup")
  116. if testEnv.DaemonInfo.CgroupVersion != "2" {
  117. assert.Assert(t, daemonCgroup == containerCgroup)
  118. } else {
  119. assert.Assert(t, daemonCgroup != containerCgroup)
  120. }
  121. }