package build // import "github.com/docker/docker/integration/build" import ( "context" "encoding/json" "io" "strings" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/requirement" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" "gotest.tools/v3/skip" ) // Finds the output of `readlink /proc//ns/cgroup` in build output func getCgroupFromBuildOutput(buildOutput io.Reader) (string, error) { const prefix = "cgroup:" dec := json.NewDecoder(buildOutput) for { m := jsonmessage.JSONMessage{} err := dec.Decode(&m) if err == io.EOF { return "", nil } if err != nil { return "", err } if ix := strings.Index(m.Stream, prefix); ix == 0 { return strings.TrimSpace(m.Stream), nil } } } // Runs a docker build against a daemon with the given cgroup namespace default value. // Returns the container cgroup and daemon cgroup. func testBuildWithCgroupNs(t *testing.T, daemonNsMode string) (string, string) { d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) d.StartWithBusybox(t) defer d.Stop(t) dockerfile := ` FROM busybox RUN readlink /proc/self/ns/cgroup ` ctx := context.Background() source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() client := d.NewClientT(t) resp, err := client.ImageBuild(ctx, source.AsTarReader(t), types.ImageBuildOptions{ Remove: true, ForceRemove: true, Tags: []string{"buildcgroupns"}, }) assert.NilError(t, err) defer resp.Body.Close() containerCgroup, err := getCgroupFromBuildOutput(resp.Body) assert.NilError(t, err) daemonCgroup := d.CgroupNamespace(t) return containerCgroup, daemonCgroup } func TestCgroupNamespacesBuild(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) // When the daemon defaults to private cgroup namespaces, containers launched // should be in their own private cgroup namespace by default containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "private") assert.Assert(t, daemonCgroup != containerCgroup) } func TestCgroupNamespacesBuildDaemonHostMode(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) // When the daemon defaults to host cgroup namespaces, containers // launched should not be inside their own cgroup namespaces containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "host") assert.Assert(t, daemonCgroup == containerCgroup) }