Merge e61dbc46b2 into 236ba5690e
				
					
				
			This commit is contained in:
		
						commit
						4ea6233c3c
					
				
							
								
								
									
										12
									
								
								README.md
								
								
								
								
							
							
						
						
									
										12
									
								
								README.md
								
								
								
								
							|  | @ -101,6 +101,7 @@ _If you are interested in contributing to kaniko, see | |||
|       - [Flag `--no-push`](#flag---no-push) | ||||
|       - [Flag `--no-push-cache`](#flag---no-push-cache) | ||||
|       - [Flag `--oci-layout-path`](#flag---oci-layout-path) | ||||
|       - [Flag `--preserve-context`](#flag---preserve-context) | ||||
|       - [Flag `--push-retry`](#flag---push-retry) | ||||
|       - [Flag `--registry-certificate`](#flag---registry-certificate) | ||||
|       - [Flag `--registry-client-cert`](#flag---registry-client-cert) | ||||
|  | @ -978,6 +979,17 @@ _Note: Depending on the built image, the media type of the image manifest might | |||
| be either `application/vnd.oci.image.manifest.v1+json` or | ||||
| `application/vnd.docker.distribution.manifest.v2+json`._ | ||||
| 
 | ||||
| #### Flag `--preserve-context` | ||||
| 
 | ||||
| Set this boolean flag to `true` if you want kaniko to restore the build-context for multi-stage builds. | ||||
| If set, kaniko will take a snapshot of the full filesystem before it starts building to later restore to that state. If combined with the `--cleanup` flag it will also restore the state after cleanup. | ||||
| 
 | ||||
| This is useful if you want to pass in secrets via files or if you want to execute commands after the build completes. | ||||
| 
 | ||||
| It will only take the snapshot if we are building a multistage image or if we plan to cleanup the filesystem after the build. | ||||
| 
 | ||||
| Defaults to `false` | ||||
| 
 | ||||
| #### Flag `--push-ignore-immutable-tag-errors` | ||||
| 
 | ||||
| Set this boolean flag to `true` if you want the Kaniko process to exit with | ||||
|  |  | |||
|  | @ -280,6 +280,7 @@ func addKanikoOptionsFlags() { | |||
| 	RootCmd.PersistentFlags().VarP(&opts.IgnorePaths, "ignore-path", "", "Ignore these paths when taking a snapshot. Set it repeatedly for multiple paths.") | ||||
| 	RootCmd.PersistentFlags().BoolVarP(&opts.ForceBuildMetadata, "force-build-metadata", "", false, "Force add metadata layers to build image") | ||||
| 	RootCmd.PersistentFlags().BoolVarP(&opts.SkipPushPermissionCheck, "skip-push-permission-check", "", false, "Skip check of the push permission") | ||||
| 	RootCmd.PersistentFlags().BoolVarP(&opts.PreserveContext, "preserve-context", "", false, "Preserve build context accross build stages by taking a snapshot of the full filesystem before build and restore it after we switch stages. Restores in the end too if passed together with 'cleanup'") | ||||
| 
 | ||||
| 	// Deprecated flags.
 | ||||
| 	RootCmd.PersistentFlags().StringVarP(&opts.SnapshotModeDeprecated, "snapshotMode", "", "", "This flag is deprecated. Please use '--snapshot-mode'.") | ||||
|  |  | |||
|  | @ -91,6 +91,7 @@ type KanikoOptions struct { | |||
| 	ForceBuildMetadata       bool | ||||
| 	InitialFSUnpacked        bool | ||||
| 	SkipPushPermissionCheck  bool | ||||
| 	PreserveContext          bool | ||||
| } | ||||
| 
 | ||||
| type KanikoGitOptions struct { | ||||
|  |  | |||
|  | @ -85,6 +85,20 @@ type stageBuilder struct { | |||
| 	pushLayerToCache cachePusher | ||||
| } | ||||
| 
 | ||||
| func makeSnapshotter(opts *config.KanikoOptions) (*snapshot.Snapshotter, error) { | ||||
| 	err := util.InitIgnoreList() | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to initialize ignore list") | ||||
| 	} | ||||
| 
 | ||||
| 	hasher, err := getHasher(opts.SnapshotMode) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	l := snapshot.NewLayeredMap(hasher) | ||||
| 	return snapshot.NewSnapshotter(l, config.RootDir), nil | ||||
| } | ||||
| 
 | ||||
| // newStageBuilder returns a new type stageBuilder which contains all the information required to build the stage
 | ||||
| func newStageBuilder(args *dockerfile.BuildArgs, opts *config.KanikoOptions, stage config.KanikoStage, crossStageDeps map[int][]string, dcm map[string]string, sid map[string]string, stageNameToIdx map[string]string, fileContext util.FileContext) (*stageBuilder, error) { | ||||
| 	sourceImage, err := image_util.RetrieveSourceImage(stage, opts) | ||||
|  | @ -101,17 +115,10 @@ func newStageBuilder(args *dockerfile.BuildArgs, opts *config.KanikoOptions, sta | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	err = util.InitIgnoreList() | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to initialize ignore list") | ||||
| 	} | ||||
| 
 | ||||
| 	hasher, err := getHasher(opts.SnapshotMode) | ||||
| 	snapshotter, err := makeSnapshotter(opts) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	l := snapshot.NewLayeredMap(hasher) | ||||
| 	snapshotter := snapshot.NewSnapshotter(l, config.RootDir) | ||||
| 
 | ||||
| 	digest, err := sourceImage.Digest() | ||||
| 	if err != nil { | ||||
|  | @ -688,6 +695,23 @@ func CalculateDependencies(stages []config.KanikoStage, opts *config.KanikoOptio | |||
| 	return depGraph, nil | ||||
| } | ||||
| 
 | ||||
| func restoreFilesystem(tarball string, opts *config.KanikoOptions) error { | ||||
| 	if err := util.DeleteFilesystem(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if opts.PreserveContext { | ||||
| 		if tarball == "" { | ||||
| 			return fmt.Errorf("context snapshot is missing") | ||||
| 		} | ||||
| 		_, err := util.UnpackLocalTarArchive(tarball, config.RootDir) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrap(err, "failed to unpack context snapshot") | ||||
| 		} | ||||
| 		logrus.Info("Context restored") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // DoBuild executes building the Dockerfile
 | ||||
| func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | ||||
| 	t := timing.Start("Total Build Time") | ||||
|  | @ -722,6 +746,24 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | |||
| 
 | ||||
| 	var args *dockerfile.BuildArgs | ||||
| 
 | ||||
| 	var tarball string | ||||
| 	if opts.PreserveContext { | ||||
| 		if len(kanikoStages) > 1 || opts.Cleanup { | ||||
| 			logrus.Info("Creating snapshot of build context") | ||||
| 			snapshotter, err := makeSnapshotter(opts) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
| 			tarball, err = snapshotter.TakeSnapshotFS() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 		} else { | ||||
| 			logrus.Info("Skipping context snapshot as no-one requires it") | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for index, stage := range kanikoStages { | ||||
| 		sb, err := newStageBuilder( | ||||
| 			args, opts, stage, | ||||
|  | @ -787,7 +829,8 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | |||
| 				} | ||||
| 			} | ||||
| 			if opts.Cleanup { | ||||
| 				if err = util.DeleteFilesystem(); err != nil { | ||||
| 				err = restoreFilesystem(tarball, opts) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 			} | ||||
|  | @ -819,8 +862,9 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | |||
| 		} | ||||
| 
 | ||||
| 		// Delete the filesystem
 | ||||
| 		if err := util.DeleteFilesystem(); err != nil { | ||||
| 			return nil, errors.Wrap(err, fmt.Sprintf("deleting file system after stage %d", index)) | ||||
| 		err = restoreFilesystem(tarball, opts) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue