diff --git a/integration/dockerfiles/Dockerfile_dockerignore_relative b/integration/dockerfiles/Dockerfile_dockerignore_relative new file mode 100644 index 0000000000..6ef2bac592 --- /dev/null +++ b/integration/dockerfiles/Dockerfile_dockerignore_relative @@ -0,0 +1,7 @@ +# This is not included in integration tests because docker build does not exploit Dockerfile.dockerignore +# See https://github.com/moby/moby/issues/12886#issuecomment-523706042 for more details +# This dockerfile makes sure Dockerfile.dockerignore is working +# If so then ignore_relative/foo should copy to /foo +# If not, then this image won't build because it will attempt to copy three files to /foo, which is a file not a directory +FROM scratch +COPY ignore_relative/* /foo diff --git a/integration/dockerfiles/Dockerfile_dockerignore_relative.dockerignore b/integration/dockerfiles/Dockerfile_dockerignore_relative.dockerignore new file mode 100644 index 0000000000..7f5371bdd8 --- /dev/null +++ b/integration/dockerfiles/Dockerfile_dockerignore_relative.dockerignore @@ -0,0 +1,3 @@ +# A .dockerignore file to make sure dockerignore support works +ignore_relative/** +!ignore_relative/foo diff --git a/integration/ignore_relative/bar b/integration/ignore_relative/bar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration/ignore_relative/baz b/integration/ignore_relative/baz new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration/ignore_relative/foo b/integration/ignore_relative/foo new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pkg/executor/build.go b/pkg/executor/build.go index e134e52b57..45f23cca39 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -427,7 +427,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { if err != nil { return nil, err } - if err := util.GetExcludedFiles(opts.SrcContext); err != nil { + if err := util.GetExcludedFiles(opts.DockerfilePath, opts.SrcContext); err != nil { return nil, err } // Some stages may refer to other random images, not previous stages diff --git a/pkg/util/command_util_test.go b/pkg/util/command_util_test.go index 3e23425951..cd1a324a2a 100644 --- a/pkg/util/command_util_test.go +++ b/pkg/util/command_util_test.go @@ -390,7 +390,7 @@ var isSrcValidTests = []struct { func Test_IsSrcsValid(t *testing.T) { for _, test := range isSrcValidTests { t.Run(test.name, func(t *testing.T) { - if err := GetExcludedFiles(buildContextPath); err != nil { + if err := GetExcludedFiles("", buildContextPath); err != nil { t.Fatalf("error getting excluded files: %v", err) } err := IsSrcsValid(test.srcsAndDest, test.resolvedSources, buildContextPath) diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 338caa02a3..cc9e4a4bde 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -554,11 +554,15 @@ func CopyFile(src, dest, buildcontext string) (bool, error) { } // GetExcludedFiles gets a list of files to exclude from the .dockerignore -func GetExcludedFiles(buildcontext string) error { - path := filepath.Join(buildcontext, ".dockerignore") +func GetExcludedFiles(dockerfilepath string, buildcontext string) error { + path := dockerfilepath + ".dockerignore" + if !FilepathExists(path) { + path = filepath.Join(buildcontext, ".dockerignore") + } if !FilepathExists(path) { return nil } + logrus.Infof("Using dockerignore file: %v", path) contents, err := ioutil.ReadFile(path) if err != nil { return errors.Wrap(err, "parsing .dockerignore") diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index c44908056f..886efcf8fe 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -694,3 +694,54 @@ func Test_childDirInWhitelist(t *testing.T) { }) } } + +func Test_correctDockerignoreFileIsUsed(t *testing.T) { + type args struct { + dockerfilepath string + buildcontext string + excluded []string + included []string + } + tests := []struct { + name string + args args + }{ + { + name: "relative dockerfile used", + args: args{ + dockerfilepath: "../../integration/dockerfiles/Dockerfile_dockerignore_relative", + buildcontext: "../../integration/", + excluded: []string{"ignore_relative/bar"}, + included: []string{"ignore_relative/foo", "ignore/bar"}, + }, + }, + { + name: "context dockerfile is used", + args: args{ + dockerfilepath: "../../integration/dockerfiles/Dockerfile_test_dockerignore", + buildcontext: "../../integration/", + excluded: []string{"ignore/bar"}, + included: []string{"ignore/foo", "ignore_relative/bar"}, + }, + }, + } + for _, tt := range tests { + if err := GetExcludedFiles(tt.args.dockerfilepath, tt.args.buildcontext); err != nil { + t.Fatal(err) + } + for _, excl := range tt.args.excluded { + t.Run(tt.name+" to exclude "+excl, func(t *testing.T) { + if !excludeFile(excl, tt.args.buildcontext) { + t.Errorf("'%v' not excluded", excl) + } + }) + } + for _, incl := range tt.args.included { + t.Run(tt.name+" to include "+incl, func(t *testing.T) { + if excludeFile(incl, tt.args.buildcontext) { + t.Errorf("'%v' not included", incl) + } + }) + } + } +}