diff --git a/integration/dockerfiles/Dockerfile_test_dockerignore b/integration/dockerfiles/Dockerfile_test_dockerignore index d825049409..b65351ca98 100644 --- a/integration/dockerfiles/Dockerfile_test_dockerignore +++ b/integration/dockerfiles/Dockerfile_test_dockerignore @@ -1,19 +1,20 @@ # This dockerfile makes sure the .dockerignore is working # If so then ignore/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 +# If not, then this image won't build because it will attempt to copy three files to /foo.txt, which is a file not a directory FROM scratch as base -COPY ignore/* /foo +COPY ignore/* /foo.txt From base as first -COPY --from=base /foo ignore/bar +COPY --from=base /foo.txt ignore/bar # Make sure that .dockerignore also applies for later stages FROM scratch as base2 -COPY ignore/* /foo +COPY ignore/* /foo.txt From base2 as second -COPY --from=base2 /foo ignore/bar +COPY --from=base2 /foo.txt ignore/bar FROM scratch +# Test make sure, dockerignore is not applied with `-from` COPY --from=first ignore/* /fooAnother/ COPY --from=second ignore/* /fooAnother2/ diff --git a/integration/dockerfiles/Dockerfile_test_dont_ignore_copy_from b/integration/dockerfiles/Dockerfile_test_dont_ignore_copy_from new file mode 100644 index 0000000000..caedc8b0f7 --- /dev/null +++ b/integration/dockerfiles/Dockerfile_test_dont_ignore_copy_from @@ -0,0 +1,5 @@ +FROM scratch as src +COPY . / + +FROM scratch as dest +COPY --from=src / . diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index b4ae40956d..6ca7e7126d 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -44,9 +44,11 @@ type CopyCommand struct { } func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error { + ignoreExcludes := false // Resolve from if c.cmd.From != "" { c.fileContext = util.FileContext{Root: filepath.Join(kConfig.KanikoDir, c.cmd.From)} + ignoreExcludes = true } replacementEnvs := buildArgs.ReplacementEnvs(config.Env) @@ -89,14 +91,14 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu } if fi.IsDir() { - copiedFiles, err := util.CopyDir(fullPath, destPath, c.fileContext, uid, gid) + copiedFiles, err := util.CopyDir(fullPath, destPath, c.fileContext, uid, gid, ignoreExcludes) if err != nil { return errors.Wrap(err, "copying dir") } c.snapshotFiles = append(c.snapshotFiles, copiedFiles...) } else if util.IsSymlink(fi) { // If file is a symlink, we want to copy the target file to destPath - exclude, err := util.CopySymlink(fullPath, destPath, c.fileContext) + exclude, err := util.CopySymlink(fullPath, destPath, c.fileContext, ignoreExcludes) if err != nil { return errors.Wrap(err, "copying symlink") } @@ -106,12 +108,19 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu c.snapshotFiles = append(c.snapshotFiles, destPath) } else { // ... Else, we want to copy over a file - exclude, err := util.CopyFile(fullPath, destPath, c.fileContext, uid, gid) - if err != nil { - return errors.Wrap(err, "copying file") - } - if exclude { - continue + if !ignoreExcludes { + exclude, err := util.CopyFile(fullPath, destPath, c.fileContext, uid, gid) + if err != nil { + return errors.Wrap(err, "copying file") + } + if exclude { + continue + } + } else { + err = util.CopyFileIgnoreExclude(fullPath, destPath, c.fileContext, uid, gid) + if err != nil { + return errors.Wrap(err, "copying file") + } } c.snapshotFiles = append(c.snapshotFiles, destPath) } diff --git a/pkg/executor/build.go b/pkg/executor/build.go index c443065704..3ba3e4372c 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -668,7 +668,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { } for _, p := range filesToSave { logrus.Infof("Saving file %s for later use", p) - if err := util.CopyFileOrSymlink(p, dstDir, config.RootDir); err != nil { + if err := util.CopyFileOrSymlink(p, dstDir, fileContext.Root); err != nil { return nil, errors.Wrap(err, "could not save file") } } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 90972e0ed0..3e8dbecf75 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -583,7 +583,7 @@ func DetermineTargetFileOwnership(fi os.FileInfo, uid, gid int64) (int64, int64) // CopyDir copies the file or directory at src to dest // It returns a list of files it copied over -func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, error) { +func CopyDir(src, dest string, context FileContext, uid, gid int64, ignoreExcludes bool) ([]string, error) { files, err := RelativeFiles("", src) if err != nil { return nil, errors.Wrap(err, "copying dir") @@ -595,7 +595,7 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, e if err != nil { return nil, errors.Wrap(err, "copying dir") } - if context.ExcludesFile(fullPath) { + if context.ExcludesFile(fullPath) && !ignoreExcludes { logrus.Debugf("%s found in .dockerignore, ignoring", src) continue } @@ -610,12 +610,12 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, e } } else if IsSymlink(fi) { // If file is a symlink, we want to create the same relative symlink - if _, err := CopySymlink(fullPath, destPath, context); err != nil { + if _, err := CopySymlink(fullPath, destPath, context, ignoreExcludes); err != nil { return nil, err } } else { // ... Else, we want to copy over a file - if _, err := CopyFile(fullPath, destPath, context, uid, gid); err != nil { + if err := CopyFileIgnoreExclude(fullPath, destPath, context, uid, gid); err != nil { return nil, err } } @@ -625,8 +625,8 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, e } // CopySymlink copies the symlink at src to dest. -func CopySymlink(src, dest string, context FileContext) (bool, error) { - if context.ExcludesFile(src) { +func CopySymlink(src, dest string, context FileContext, ignoreExcludes bool) (bool, error) { + if context.ExcludesFile(src) && !ignoreExcludes { logrus.Debugf("%s found in .dockerignore, ignoring", src) return true, nil } @@ -645,30 +645,35 @@ func CopySymlink(src, dest string, context FileContext) (bool, error) { return false, os.Symlink(link, dest) } -// CopyFile copies the file at src to dest -func CopyFile(src, dest string, context FileContext, uid, gid int64) (bool, error) { - if context.ExcludesFile(src) { - logrus.Debugf("%s found in .dockerignore, ignoring", src) - return true, nil - } +// CopyFileIgnoreExclude copies the file at src to dest without checking excludes +func CopyFileIgnoreExclude(src, dest string, context FileContext, uid, gid int64) error { if src == dest { - // This is a no-op. Move on, but don't list it as ignored. + // This is a no-op. // We have to make sure we do this so we don't overwrite our own file. // See iusse #904 for an example. - return false, nil + return nil } fi, err := os.Stat(src) if err != nil { - return false, err + return err } logrus.Debugf("Copying file %s to %s", src, dest) srcFile, err := os.Open(src) if err != nil { - return false, err + return err } defer srcFile.Close() uid, gid = DetermineTargetFileOwnership(fi, uid, gid) - return false, CreateFile(dest, srcFile, fi.Mode(), uint32(uid), uint32(gid)) + return CreateFile(dest, srcFile, fi.Mode(), uint32(uid), uint32(gid)) +} + +// CopyFile copies the file at src to dest, unless it is excluded +func CopyFile(src, dest string, context FileContext, uid, gid int64) (bool, error) { + if context.ExcludesFile(src) { + logrus.Debugf("%s found in .dockerignore, ignoring", src) + return true, nil + } + return false, CopyFileIgnoreExclude(src, dest, context, uid, gid) } func NewFileContextFromDockerfile(dockerfilePath, buildcontext string) (FileContext, error) { diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index f5d83c91a9..8c4a1f3fe5 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -880,7 +880,7 @@ func TestCopySymlink(t *testing.T) { if err := os.Symlink(tc.linkTarget, link); err != nil { t.Fatal(err) } - if _, err := CopySymlink(link, dest, FileContext{}); err != nil { + if _, err := CopySymlink(link, dest, FileContext{}, false); err != nil { t.Fatal(err) } if _, err := os.Lstat(dest); err != nil {