From 8bd1d2811e332fdd49714be8482f9a5cef0eef2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 9 Apr 2024 20:30:09 +0200 Subject: [PATCH] fix: handle dockerignore exclusions properly (#2476) * chore: only include the dockerignore if it contains ignore files * fix: the inclusions must be relative to the context * docs: document the dockerignore feature * chore: only include the dockerignore file if it exists --- container.go | 22 ++++++++++++++++------ container_ignore_test.go | 11 ++++++++++- docs/features/build_from_dockerfile.md | 10 +++++++++- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/container.go b/container.go index 249aff32cf..00da75783d 100644 --- a/container.go +++ b/container.go @@ -221,13 +221,17 @@ func (c *ContainerRequest) GetContext() (io.Reader, error) { } c.Context = abs - excluded, err := parseDockerIgnore(abs) + dockerIgnoreExists, excluded, err := parseDockerIgnore(abs) if err != nil { return nil, err } - dockerIgnoreLocation := filepath.Join(abs, ".dockerignore") - includes = append(includes, dockerIgnoreLocation, c.GetDockerfile()) + if dockerIgnoreExists { + // only add .dockerignore if it exists + includes = append(includes, filepath.Join(".dockerignore")) + } + + includes = append(includes, c.GetDockerfile()) buildContext, err := archive.TarWithOptions( c.Context, @@ -240,18 +244,24 @@ func (c *ContainerRequest) GetContext() (io.Reader, error) { return buildContext, nil } -func parseDockerIgnore(targetDir string) ([]string, error) { +// parseDockerIgnore returns if the file exists, the excluded files and an error if any +func parseDockerIgnore(targetDir string) (bool, []string, error) { // based on https://github.com/docker/cli/blob/master/cli/command/image/build/dockerignore.go#L14 fileLocation := filepath.Join(targetDir, ".dockerignore") var excluded []string + exists := false if f, openErr := os.Open(fileLocation); openErr == nil { + defer f.Close() + + exists = true + var err error excluded, err = ignorefile.ReadAll(f) if err != nil { - return excluded, fmt.Errorf("error reading .dockerignore: %w", err) + return true, excluded, fmt.Errorf("error reading .dockerignore: %w", err) } } - return excluded, nil + return exists, excluded, nil } // GetBuildArgs returns the env args to be used when creating from Dockerfile diff --git a/container_ignore_test.go b/container_ignore_test.go index 566697c980..ca89db4d89 100644 --- a/container_ignore_test.go +++ b/container_ignore_test.go @@ -11,23 +11,32 @@ import ( func TestParseDockerIgnore(t *testing.T) { testCases := []struct { filePath string + exists bool expectedErr error expectedExcluded []string }{ { filePath: "./testdata/dockerignore", expectedErr: nil, + exists: true, expectedExcluded: []string{"vendor", "foo", "bar"}, }, { filePath: "./testdata", expectedErr: nil, + exists: true, expectedExcluded: []string{"Dockerfile", "echo.Dockerfile"}, }, + { + filePath: "./testdata/data", + expectedErr: nil, + expectedExcluded: nil, // it's nil because the parseDockerIgnore function uses the zero value of a slice + }, } for _, testCase := range testCases { - excluded, err := parseDockerIgnore(testCase.filePath) + exists, excluded, err := parseDockerIgnore(testCase.filePath) + assert.Equal(t, testCase.exists, exists) assert.Equal(t, testCase.expectedErr, err) assert.Equal(t, testCase.expectedExcluded, excluded) } diff --git a/docs/features/build_from_dockerfile.md b/docs/features/build_from_dockerfile.md index 19ad060d2e..a3be26212a 100644 --- a/docs/features/build_from_dockerfile.md +++ b/docs/features/build_from_dockerfile.md @@ -33,7 +33,6 @@ You can specify them like: If you would like to send a build context that you created in code (maybe you have a dynamic Dockerfile), you can send the build context as an `io.Reader` since the Docker Daemon accepts it as a tar file, you can use the [tar](https://golang.org/pkg/archive/tar/) package to create your context. - To do this you would use the `ContextArchive` attribute in the `FromDockerfile` struct. ```go @@ -52,6 +51,15 @@ fromDockerfile := testcontainers.FromDockerfile{ **Please Note** if you specify a `ContextArchive` this will cause _Testcontainers for Go_ to ignore the path passed in to `Context`. +## Ignoring files in the build context + +The same as Docker has a `.dockerignore` file to ignore files in the build context, _Testcontainers for Go_ also supports this feature. +A `.dockerignore` living in the root of the build context will be used to filter out files that should not be sent to the Docker daemon. +The `.dockerignore` file won't be sent to the Docker daemon either. + +!!! note + At this moment, _Testcontainers for Go_ does not support Dockerfile-specific `.dockerignore` files. + ## Images requiring auth If you are building a local Docker image that is fetched from a Docker image in a registry requiring authentication