run_cgroupns_linux_test.go 5.9 KB

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