diff --git a/pkg/commands/base_command.go b/pkg/commands/base_command.go index 698b72821..fe6a45c71 100644 --- a/pkg/commands/base_command.go +++ b/pkg/commands/base_command.go @@ -39,3 +39,7 @@ func (b *BaseCommand) FilesUsedFromContext(_ *v1.Config, _ *dockerfile.BuildArgs func (b *BaseCommand) MetadataOnly() bool { return true } + +func (b *BaseCommand) RequiresUnpackedFS() bool { + return false +} diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index d6ed04b59..b8acade2c 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -43,6 +43,8 @@ type DockerCommand interface { FilesUsedFromContext(*v1.Config, *dockerfile.BuildArgs) ([]string, error) MetadataOnly() bool + + RequiresUnpackedFS() bool } func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, error) { diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 72772922b..5295cab82 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -165,6 +165,10 @@ func (r *RunCommand) MetadataOnly() bool { return false } +func (r *RunCommand) RequiresUnpackedFS() bool { + return true +} + type CachingRunCommand struct { BaseCommand img v1.Image diff --git a/pkg/executor/build.go b/pkg/executor/build.go index 62ad15629..f039fb5ca 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -86,14 +86,11 @@ func newStageBuilder(opts *config.KanikoOptions, stage config.KanikoStage) (*sta }, nil } -func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config, cmds []commands.DockerCommand) error { +func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config, cmds []commands.DockerCommand, args *dockerfile.BuildArgs) error { if !s.opts.Cache { return nil } - args := dockerfile.NewBuildArgs(s.opts.BuildArgs) - args.AddMetaArgs(s.stage.MetaArgs) - layerCache := &cache.RegistryCache{ Opts: s.opts, } @@ -144,15 +141,6 @@ func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config, cmds } func (s *stageBuilder) build() error { - // Unpack file system to root - if _, err := util.GetFSFromImage(constants.RootDir, s.image); err != nil { - return err - } - // Take initial snapshot - if err := s.snapshotter.Init(); err != nil { - return err - } - // Set the initial cache key to be the base image digest, the build args and the SrcContext. compositeKey := NewCompositeCache(s.baseImageDigest) compositeKey.AddKey(s.opts.BuildArgs...) @@ -170,9 +158,32 @@ func (s *stageBuilder) build() error { args.AddMetaArgs(s.stage.MetaArgs) // Apply optimizations to the instructions. - if err := s.optimize(*compositeKey, s.cf.Config, cmds); err != nil { + if err := s.optimize(*compositeKey, s.cf.Config, cmds, args); err != nil { return err } + + // Unpack file system to root if we need to. + shouldUnpack := false + for _, cmd := range cmds { + if cmd.RequiresUnpackedFS() { + logrus.Infof("Unpacking rootfs as cmd %s requires it.", cmd.String()) + shouldUnpack = true + break + } + } + if shouldUnpack { + if _, err := util.GetFSFromImage(constants.RootDir, s.image); err != nil { + return err + } + } + if err := util.DetectFilesystemWhitelist(constants.WhitelistPath); err != nil { + return err + } + // Take initial snapshot + if err := s.snapshotter.Init(); err != nil { + return err + } + for index, command := range cmds { if command == nil { continue diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index fd53ee7bf..a0778bb18 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -62,8 +62,7 @@ var whitelist = []WhitelistEntry{ // GetFSFromImage extracts the layers of img to root // It returns a list of all files extracted func GetFSFromImage(root string, img v1.Image) ([]string, error) { - whitelist, err := fileSystemWhitelist(constants.WhitelistPath) - if err != nil { + if err := DetectFilesystemWhitelist(constants.WhitelistPath); err != nil { return nil, err } logrus.Debugf("Mounted directories: %v", whitelist) @@ -303,10 +302,10 @@ func checkWhitelistRoot(root string) bool { // (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) // Where (5) is the mount point relative to the process's root // From: https://www.kernel.org/doc/Documentation/filesystems/proc.txt -func fileSystemWhitelist(path string) ([]WhitelistEntry, error) { +func DetectFilesystemWhitelist(path string) error { f, err := os.Open(path) if err != nil { - return nil, err + return err } defer f.Close() reader := bufio.NewReader(f) @@ -314,7 +313,7 @@ func fileSystemWhitelist(path string) ([]WhitelistEntry, error) { line, err := reader.ReadString('\n') logrus.Debugf("Read the following line from %s: %s", path, line) if err != nil && err != io.EOF { - return nil, err + return err } lineArr := strings.Split(line, " ") if len(lineArr) < 5 { @@ -336,7 +335,7 @@ func fileSystemWhitelist(path string) ([]WhitelistEntry, error) { break } } - return whitelist, nil + return nil } // RelativeFiles returns a list of all files at the filepath relative to root diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 968cacf99..20f80820e 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -29,7 +29,7 @@ import ( "github.com/GoogleContainerTools/kaniko/testutil" ) -func Test_fileSystemWhitelist(t *testing.T) { +func Test_DetectFilesystemWhitelist(t *testing.T) { testDir, err := ioutil.TempDir("", "") if err != nil { t.Fatalf("Error creating tempdir: %s", err) @@ -49,7 +49,7 @@ func Test_fileSystemWhitelist(t *testing.T) { t.Fatalf("Error writing file contents to %s: %s", path, err) } - actualWhitelist, err := fileSystemWhitelist(path) + err = DetectFilesystemWhitelist(path) expectedWhitelist := []WhitelistEntry{ {"/kaniko", false}, {"/proc", false}, @@ -59,6 +59,7 @@ func Test_fileSystemWhitelist(t *testing.T) { {"/var/run", false}, {"/etc/mtab", false}, } + actualWhitelist := whitelist sort.Slice(actualWhitelist, func(i, j int) bool { return actualWhitelist[i].Path < actualWhitelist[j].Path })