build_squash_test.go 3.0 KB

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