build_squash_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package build
  2. import (
  3. "bytes"
  4. "context"
  5. "io"
  6. "io/ioutil"
  7. "strings"
  8. "testing"
  9. "github.com/docker/docker/api/types"
  10. dclient "github.com/docker/docker/client"
  11. "github.com/docker/docker/integration/internal/container"
  12. "github.com/docker/docker/internal/test/daemon"
  13. "github.com/docker/docker/internal/test/fakecontext"
  14. "github.com/docker/docker/pkg/stdcopy"
  15. "gotest.tools/assert"
  16. is "gotest.tools/assert/cmp"
  17. "gotest.tools/skip"
  18. )
  19. func TestBuildSquashParent(t *testing.T) {
  20. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  21. var client dclient.APIClient
  22. if !testEnv.DaemonInfo.ExperimentalBuild {
  23. skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon")
  24. d := daemon.New(t, daemon.WithExperimental)
  25. d.StartWithBusybox(t)
  26. defer d.Stop(t)
  27. client = d.NewClientT(t)
  28. } else {
  29. client = testEnv.APIClient()
  30. }
  31. dockerfile := `
  32. FROM busybox
  33. RUN echo hello > /hello
  34. RUN echo world >> /hello
  35. RUN echo hello > /remove_me
  36. ENV HELLO world
  37. RUN rm /remove_me
  38. `
  39. // build and get the ID that we can use later for history comparison
  40. ctx := context.Background()
  41. source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))
  42. defer source.Close()
  43. name := "test"
  44. resp, err := client.ImageBuild(ctx,
  45. source.AsTarReader(t),
  46. types.ImageBuildOptions{
  47. Remove: true,
  48. ForceRemove: true,
  49. Tags: []string{name},
  50. })
  51. assert.NilError(t, err)
  52. _, err = io.Copy(ioutil.Discard, resp.Body)
  53. resp.Body.Close()
  54. assert.NilError(t, err)
  55. inspect, _, err := client.ImageInspectWithRaw(ctx, name)
  56. assert.NilError(t, err)
  57. origID := inspect.ID
  58. // build with squash
  59. resp, err = client.ImageBuild(ctx,
  60. source.AsTarReader(t),
  61. types.ImageBuildOptions{
  62. Remove: true,
  63. ForceRemove: true,
  64. Squash: true,
  65. Tags: []string{name},
  66. })
  67. assert.NilError(t, err)
  68. _, err = io.Copy(ioutil.Discard, resp.Body)
  69. resp.Body.Close()
  70. assert.NilError(t, err)
  71. cid := container.Run(t, ctx, client,
  72. container.WithImage(name),
  73. container.WithCmd("/bin/sh", "-c", "cat /hello"),
  74. )
  75. reader, err := client.ContainerLogs(ctx, cid, types.ContainerLogsOptions{
  76. ShowStdout: true,
  77. })
  78. assert.NilError(t, err)
  79. actualStdout := new(bytes.Buffer)
  80. actualStderr := ioutil.Discard
  81. _, err = stdcopy.StdCopy(actualStdout, actualStderr, reader)
  82. assert.NilError(t, err)
  83. assert.Check(t, is.Equal(strings.TrimSpace(actualStdout.String()), "hello\nworld"))
  84. container.Run(t, ctx, client,
  85. container.WithImage(name),
  86. container.WithCmd("/bin/sh", "-c", "[ ! -f /remove_me ]"),
  87. )
  88. container.Run(t, ctx, client,
  89. container.WithImage(name),
  90. container.WithCmd("/bin/sh", "-c", `[ "$(echo $HELLO)" == "world" ]`),
  91. )
  92. origHistory, err := client.ImageHistory(ctx, origID)
  93. assert.NilError(t, err)
  94. testHistory, err := client.ImageHistory(ctx, name)
  95. assert.NilError(t, err)
  96. inspect, _, err = client.ImageInspectWithRaw(ctx, name)
  97. assert.NilError(t, err)
  98. assert.Check(t, is.Len(testHistory, len(origHistory)+1))
  99. assert.Check(t, is.Len(inspect.RootFS.Layers, 2))
  100. }