Skip to content

Commit

Permalink
Support additional .dockerignore formats (#579)
Browse files Browse the repository at this point in the history
* Add function to map additional dockerignore files.

Docker maps "Dockerfile" to a ".dockerignore" file,
and it maps "Dockerfile-prod" to "Dockerfile-prod.dockerignore".

This commit adds a function and unit tests to map the Docker project's
dockerignore file to its expected location.

* Add integration tests for .dockerignore

While these tests cannot precisely verify whether or not a file was correctly
ignored, the docker image being build can expect the
existence/nonexistence of a file in the context tarball and fail
accordingly.

* pacify linter

* remove experimental test
  • Loading branch information
guineveresaenger authored Apr 4, 2023
1 parent b2e386a commit e6c6872
Show file tree
Hide file tree
Showing 29 changed files with 220 additions and 2 deletions.
68 changes: 68 additions & 0 deletions examples/dockerfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,71 @@ func TestDockerfileInContextYAML(t *testing.T) {
SkipRefresh: true,
})
}

func TestDockerignoreDefaultYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-default"),
Quick: true,
SkipRefresh: true,
})
}

func TestDockerignoreSpecifiedYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-specified"),
Quick: true,
SkipRefresh: true,
})
}

func TestDockerignoreDefaultFailYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-default-fail"),
Quick: true,
SkipRefresh: true,
ExpectFailure: true,
})
}

func TestDockerignoreNoMappingYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}
// we expect this test to succeed, as we test that the ignore.txt file does in fact _not_ get ignored
// the ignore.txt file does not get ignored, as .dockerignore does not map to Mockerfile.
// The RUN command in Mockerfile therefore succeeds.
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-no-mapping"),
Quick: true,
SkipRefresh: true,
})
}

func TestDockerignoreWithExternalDockerfileYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-with-external-dockerfile"),
Quick: true,
SkipRefresh: true,
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore.txt
8 changes: 8 additions & 0 deletions examples/test-dockerfile/dockerignore-default-fail/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM --platform=linux/amd64 ubuntu

COPY . /

RUN cat app.txt

Run cat ignore.txt

13 changes: 13 additions & 0 deletions examples/test-dockerfile/dockerignore-default-fail/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: dockerfile-default
runtime: yaml
resources:
demo-image:
type: docker:Image
properties:
imageName: pulumibot/ignore-image:tag2
skipPush: true
options:
version: v4.0.0
outputs:
imageName: ${demo-image.imageName}
out-dockerfile: ${demo-image.dockerfile}
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-default-fail/app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I am a test file!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I should get ignored!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore.txt
3 changes: 3 additions & 0 deletions examples/test-dockerfile/dockerignore-default/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM scratch

COPY . /
13 changes: 13 additions & 0 deletions examples/test-dockerfile/dockerignore-default/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: dockerfile-default
runtime: yaml
resources:
demo-image:
type: docker:Image
properties:
imageName: pulumibot/ignore-image:tag1
skipPush: true
options:
version: v4.0.0
outputs:
imageName: ${demo-image.imageName}
out-dockerfile: ${demo-image.dockerfile}
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-default/app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I am a test file!
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-default/ignore.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I should get ignored!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore.txt
7 changes: 7 additions & 0 deletions examples/test-dockerfile/dockerignore-no-mapping/Mockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM --platform=linux/amd64 ubuntu

COPY . /

Run cat app.txt

RUN cat ignore.txt
16 changes: 16 additions & 0 deletions examples/test-dockerfile/dockerignore-no-mapping/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: dockerfile-default
runtime: yaml
resources:
demo-image:
type: docker:Image
properties:
imageName: pulumibot/ignore-image:tag4
skipPush: true
build:
context: .
dockerfile: Mockerfile
options:
version: v4.0.0
outputs:
imageName: ${demo-image.imageName}
out-dockerfile: ${demo-image.dockerfile}
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-no-mapping/app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I am a test file!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I should get ignored!
3 changes: 3 additions & 0 deletions examples/test-dockerfile/dockerignore-specified/Mockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM --platform=linux/amd64 ubuntu

COPY . /
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore.txt
16 changes: 16 additions & 0 deletions examples/test-dockerfile/dockerignore-specified/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: dockerfile-default
runtime: yaml
resources:
demo-image:
type: docker:Image
properties:
imageName: pulumibot/ignore-image:tag3
skipPush: true
build:
context: .
dockerfile: Mockerfile
options:
version: v4.0.0
outputs:
imageName: ${demo-image.imageName}
out-dockerfile: ${demo-image.dockerfile}
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-specified/app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I am a test file!
1 change: 1 addition & 0 deletions examples/test-dockerfile/dockerignore-specified/ignore.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I should get ignored!
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM --platform=linux/amd64 ubuntu

COPY . /

RUN cat app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: dockerfile-external
runtime: yaml
resources:
demo-image:
type: docker:Image
properties:
imageName: pulumibot/test-image:tag3
skipPush: true
build:
context: ./app
dockerfile: ./Dockerfile
options:
version: v4.0.0
outputs:
imageName: ${demo-image.imageName}
out-dockerfile: ${demo-image.dockerfile}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi! I am a test file!
Empty file.
21 changes: 20 additions & 1 deletion provider/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
}

// make the build context and ensure to exclude dockerignore file patterns
dockerIgnorePath := filepath.Join(build.Context, ".dockerignore")
// map the expected location for dockerignore
dockerignore := mapDockerignore(filepath.Base(build.Dockerfile))
dockerIgnorePath := filepath.Join(build.Context, dockerignore)

initialIgnorePatterns, err := getIgnore(dockerIgnorePath)
if err != nil {
return "", nil, fmt.Errorf("error reading ignore file: %w", err)
Expand Down Expand Up @@ -806,3 +809,19 @@ func defaultPooledTransport() *http.Transport {
}
return transport
}

func mapDockerignore(dockerfile string) string {
// Docker maps `Dockerfile` -> `.dockerignore`
// Nonstandard dockerfile names map to a file with a `.dockerignore` extension
// e.g. `Mockerfile` -> `Mockerfile.dockerignore`
// Note that we do not verify the existence of a .dockerignore file; we only map the name that it would have.

ignore := ".dockerignore"

// Add extension for nonstandardly named Dockerfiles
if dockerfile != defaultDockerfile {
ignore = dockerfile + ignore
}
// Return the default dockerignore name.
return ignore
}
17 changes: 17 additions & 0 deletions provider/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,20 @@ func TestConfigureDockerClient(t *testing.T) {
})

}

func TestMapDockerignore(t *testing.T) {

t.Run("Returns default .dockerignore", func(t *testing.T) {
expected := ".dockerignore"
input := defaultDockerfile
actual := mapDockerignore(input)
assert.Equal(t, expected, actual)
})
t.Run("Returns .dockerignore extension for nonstandard dockerfile names", func(t *testing.T) {
expected := "special.dockerfile.dockerignore"
input := "special.dockerfile"
actual := mapDockerignore(input)
assert.Equal(t, expected, actual)
})

}
2 changes: 1 addition & 1 deletion provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ func (accumulator *contextHashAccumulator) hexSumContext() string {

func hashContext(dockerContextPath string, dockerfile string) (string, error) {
// exclude all files listed in dockerignore
dockerIgnorePath := filepath.Join(dockerContextPath, ".dockerignore")
dockerIgnorePath := filepath.Join(dockerContextPath, mapDockerignore(filepath.Base(dockerfile)))
ignorePatterns, err := getIgnore(dockerIgnorePath)
if err != nil {
return "", err
Expand Down

0 comments on commit e6c6872

Please sign in to comment.