https://github.com/thediveo/morbyd is a thin layer on top of the standard Docker Go client to easily build and run throw-away test Docker images and containers, and running commands inside them. It features a function option API to keep the slightly excessive Docker API option parameters at bay. (And large test coverage FWIW).
You might ask: why, when there's ory/dockertest/v3? Because their Ory's proprietary Docker client (predating the canonical one) is incompatible with the Docker daemon's 100 CONTINUE header when streaming container and command stdout/stderr. I've reported this, but did not got any response at all, so I finally cut my losses and wrote "morbyd" to be able to move on. The proper Docker client allows me to easily dump and analyse build and container output when tests go south. Below is how morbyd feels, compared to ory/dockertest/v3, to give you an idea which API design might be better suited for you (or not): dockertest (using Gomega for assertions): Expect(pool.Client.BuildImage(docker.BuildImageOptions{ Name: img.Name, ContextDir: "./test/_kindisch", // sorry, couldn't resist the pun. Dockerfile: "Dockerfile", BuildArgs: []docker.BuildArg{ {Name: "KINDEST_BASE_TAG", Value: test.KindestBaseImageTag}, }, OutputStream: io.Discard, })).To(Succeed()) providerCntr := Successful(pool.RunWithOptions( &dockertest.RunOptions{ Name: kindischName, Repository: img.Name, Privileged: true, Mounts: []string{ "/var", // well, this actually is an unnamed volume "/dev/mapper:/dev/mapper", "/lib/modules:/lib/modules:ro", }, Tty: true, }, func(hc *docker.HostConfig) { hc.Init = false hc.Tmpfs = map[string]string{ "/tmp": "", "/run": "", } hc.Devices = []docker.Device{ {PathOnHost: "/dev/fuse"}, } })) morbyd (also using Gomega for assertions): Expect(sess.BuildImage(ctx, "./test/_kindisch", build.WithTag(img.Name), build.WithBuildArg("KINDEST_BASE_TAG="+test.KindestBaseImageTag), build.WithOutput(timestamper.New(GinkgoWriter)))). Error().NotTo(HaveOccurred()) providerCntr := Successful(sess.Run(ctx, img.Name, run.WithName(kindischName), run.WithAutoRemove(), run.WithPrivileged(), run.WithSecurityOpt("label=disable"), run.WithCgroupnsMode("private"), run.WithVolume("/var"), run.WithVolume("/dev/mapper:/dev/mapper"), run.WithVolume("/lib/modules:/lib/modules:ro"), run.WithTmpfs("/tmp"), run.WithTmpfs("/run"), run.WithDevice("/dev/fuse"), run.WithCombinedOutput(timestamper.New(GinkgoWriter)))) Some of these options are not simply writing their arg in the same-name struct field, but instead are parsing things, preferably in the same way as the Docker CLI does. So the transition from CLI args to unit test args should be much smoother without having to dig deep into the Docker API parameter details. While I tried to strive for more option completeness than just my own minimal viable proof, there surely a bits and pieces missing. In case morbyd might be interesting for you, I would be glad to hear from you and also missing pieces; and preferably a PR if you would be so kind. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/34643167-7222-4e7a-a1a8-79d757c2c8fen%40googlegroups.com.