summaryrefslogtreecommitdiff
path: root/integration/build/build_squash_test.go
blob: 2e8e45604b2559b70b3a27a9b682cd176786dabe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package build

import (
	"bytes"
	"context"
	"io"
	"strings"
	"testing"

	"github.com/docker/docker/api/types"
	dclient "github.com/docker/docker/client"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/pkg/stdcopy"
	"github.com/docker/docker/testutil/daemon"
	"github.com/docker/docker/testutil/fakecontext"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
	"gotest.tools/v3/skip"
)

func TestBuildSquashParent(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType == "windows")

	var client dclient.APIClient
	if !testEnv.DaemonInfo.ExperimentalBuild {
		skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon")

		d := daemon.New(t, daemon.WithExperimental())
		d.StartWithBusybox(t)
		defer d.Stop(t)
		client = d.NewClientT(t)
	} else {
		client = testEnv.APIClient()
	}

	dockerfile := `
		FROM busybox
		RUN echo hello > /hello
		RUN echo world >> /hello
		RUN echo hello > /remove_me
		ENV HELLO world
		RUN rm /remove_me
		`

	// build and get the ID that we can use later for history comparison
	ctx := context.Background()
	source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))
	defer source.Close()

	name := strings.ToLower(t.Name())
	resp, err := client.ImageBuild(ctx,
		source.AsTarReader(t),
		types.ImageBuildOptions{
			Remove:      true,
			ForceRemove: true,
			Tags:        []string{name},
		})
	assert.NilError(t, err)
	_, err = io.Copy(io.Discard, resp.Body)
	resp.Body.Close()
	assert.NilError(t, err)

	inspect, _, err := client.ImageInspectWithRaw(ctx, name)
	assert.NilError(t, err)
	origID := inspect.ID

	// build with squash
	resp, err = client.ImageBuild(ctx,
		source.AsTarReader(t),
		types.ImageBuildOptions{
			Remove:      true,
			ForceRemove: true,
			Squash:      true,
			Tags:        []string{name},
		})
	assert.NilError(t, err)
	_, err = io.Copy(io.Discard, resp.Body)
	resp.Body.Close()
	assert.NilError(t, err)

	cid := container.Run(ctx, t, client,
		container.WithImage(name),
		container.WithCmd("/bin/sh", "-c", "cat /hello"),
	)
	reader, err := client.ContainerLogs(ctx, cid, types.ContainerLogsOptions{
		ShowStdout: true,
	})
	assert.NilError(t, err)

	actualStdout := new(bytes.Buffer)
	actualStderr := io.Discard
	_, err = stdcopy.StdCopy(actualStdout, actualStderr, reader)
	assert.NilError(t, err)
	assert.Check(t, is.Equal(strings.TrimSpace(actualStdout.String()), "hello\nworld"))

	container.Run(ctx, t, client,
		container.WithImage(name),
		container.WithCmd("/bin/sh", "-c", "[ ! -f /remove_me ]"),
	)
	container.Run(ctx, t, client,
		container.WithImage(name),
		container.WithCmd("/bin/sh", "-c", `[ "$(echo $HELLO)" = "world" ]`),
	)

	origHistory, err := client.ImageHistory(ctx, origID)
	assert.NilError(t, err)
	testHistory, err := client.ImageHistory(ctx, name)
	assert.NilError(t, err)

	inspect, _, err = client.ImageInspectWithRaw(ctx, name)
	assert.NilError(t, err)
	assert.Check(t, is.Len(testHistory, len(origHistory)+1))
	assert.Check(t, is.Len(inspect.RootFS.Layers, 2))
}