# dockerutil This package is for creating and controlling docker containers for testing runsc, gVisor's docker/kubernetes binary. A simple test may look like: ``` func TestSuperCool(t *testing.T) { ctx := context.Background() c := dockerutil.MakeContainer(ctx, t) got, err := c.Run(ctx, dockerutil.RunOpts{ Image: "basic/alpine" }, "echo", "super cool") if err != nil { t.Fatalf("err was not nil: %v", err) } want := "super cool" if !strings.Contains(got, want){ t.Fatalf("want: %s, got: %s", want, got) } } ``` For further examples, see many of our end to end tests elsewhere in the repo, such as those in //test/e2e or benchmarks at //test/benchmarks. dockerutil uses the "official" docker golang api, which is [very powerful](https://godoc.org/github.com/docker/docker/client). dockerutil is a thin wrapper around this API, allowing desired new use cases to be easily implemented. ## Profiling dockerutil is capable of generating profiles. Currently, the only option is to use pprof profiles generated by `runsc debug`. The profiler will generate Block, CPU, Heap, Goroutine, and Mutex profiles. To generate profiles: * Install runsc with the `--profile` flag: `make configure RUNTIME=myrunsc ARGS="--profile"` Also add other flags with ARGS like `--platform=kvm` or `--vfs2`. * Restart docker: `sudo service docker restart` To run and generate CPU profiles run: ``` make sudo TARGETS=//path/to:target \ ARGS="--runtime=myrunsc -test.v -test.bench=. --pprof-cpu" OPTIONS="-c opt" ``` Profiles would be at: `/tmp/profile/myrunsc/CONTAINERNAME/cpu.pprof` Container name in most tests and benchmarks in gVisor is usually the test name and some random characters like so: `BenchmarkABSL-CleanCache-JF2J2ZYF3U7SL47QAA727CSJI3C4ZAW2` Profiling requires root as runsc debug inspects running containers in /var/run among other things. ### Writing for Profiling The below shows an example of using profiles with dockerutil. ``` func TestSuperCool(t *testing.T){ ctx := context.Background() // profiled and using runtime from dockerutil.runtime flag profiled := MakeContainer() // not profiled and using runtime runc native := MakeNativeContainer() err := profiled.Spawn(ctx, RunOpts{ Image: "some/image", }, "sleep", "100000") // profiling has begun here ... expensive setup that I don't want to profile. ... profiled.RestartProfiles() // profiled activity } ``` In the above example, `profiled` would be profiled and `native` would not. The call to `RestartProfiles()` restarts the clock on profiling. This is useful if the main activity being tested is done with `docker exec` or `container.Spawn()` followed by one or more `container.Exec()` calls.