Add support for .dockerignore file
This commit is contained in:
		
							parent
							
								
									adac8d495d
								
							
						
					
					
						commit
						3fc43f4c73
					
				|  | @ -321,10 +321,6 @@ _This flag must be used in conjunction with the `--cache=true` flag._ | ||||||
| 
 | 
 | ||||||
| Set this flag to cleanup the filesystem at the end, leaving a clean kaniko container (if you want to build multiple images in the same container, using the debug kaniko image) | Set this flag to cleanup the filesystem at the end, leaving a clean kaniko container (if you want to build multiple images in the same container, using the debug kaniko image) | ||||||
| 
 | 
 | ||||||
| #### --ignore |  | ||||||
| 
 |  | ||||||
| Set this flag to ignore files in your build context. For examples, set `--ignore pkg/*` to ignore all files in the `pkg` directory.  |  | ||||||
| 
 |  | ||||||
| ### Debug Image | ### Debug Image | ||||||
| 
 | 
 | ||||||
| The kaniko executor image is based off of scratch and doesn't contain a shell. | The kaniko executor image is based off of scratch and doesn't contain a shell. | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ import ( | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/buildcontext" | 	"github.com/GoogleContainerTools/kaniko/pkg/buildcontext" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/dockerfile" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/executor" | 	"github.com/GoogleContainerTools/kaniko/pkg/executor" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/util" | 	"github.com/GoogleContainerTools/kaniko/pkg/util" | ||||||
| 	"github.com/genuinetools/amicontained/container" | 	"github.com/genuinetools/amicontained/container" | ||||||
|  | @ -94,7 +95,6 @@ func addKanikoOptionsFlags(cmd *cobra.Command) { | ||||||
| 	RootCmd.PersistentFlags().VarP(&opts.Destinations, "destination", "d", "Registry the final image should be pushed to. Set it repeatedly for multiple destinations.") | 	RootCmd.PersistentFlags().VarP(&opts.Destinations, "destination", "d", "Registry the final image should be pushed to. Set it repeatedly for multiple destinations.") | ||||||
| 	RootCmd.PersistentFlags().StringVarP(&opts.SnapshotMode, "snapshotMode", "", "full", "Change the file attributes inspected during snapshotting") | 	RootCmd.PersistentFlags().StringVarP(&opts.SnapshotMode, "snapshotMode", "", "full", "Change the file attributes inspected during snapshotting") | ||||||
| 	RootCmd.PersistentFlags().VarP(&opts.BuildArgs, "build-arg", "", "This flag allows you to pass in ARG values at build time. Set it repeatedly for multiple values.") | 	RootCmd.PersistentFlags().VarP(&opts.BuildArgs, "build-arg", "", "This flag allows you to pass in ARG values at build time. Set it repeatedly for multiple values.") | ||||||
| 	RootCmd.PersistentFlags().VarP(&opts.Ignore, "ignore", "", "Set this flag to ignore files in the build context. Set it repeatedly for multiple values.") |  | ||||||
| 	RootCmd.PersistentFlags().BoolVarP(&opts.InsecurePush, "insecure", "", false, "Push to insecure registry using plain HTTP") | 	RootCmd.PersistentFlags().BoolVarP(&opts.InsecurePush, "insecure", "", false, "Push to insecure registry using plain HTTP") | ||||||
| 	RootCmd.PersistentFlags().BoolVarP(&opts.SkipTLSVerify, "skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") | 	RootCmd.PersistentFlags().BoolVarP(&opts.SkipTLSVerify, "skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") | ||||||
| 	RootCmd.PersistentFlags().StringVarP(&opts.TarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing") | 	RootCmd.PersistentFlags().StringVarP(&opts.TarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing") | ||||||
|  | @ -187,23 +187,34 @@ func resolveSourceContext() error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func removeIgnoredFiles() error { | func removeIgnoredFiles() error { | ||||||
| 	logrus.Infof("Removing ignored files from build context: %s", opts.Ignore) | 	if !dockerfile.DockerignoreExists(opts) { | ||||||
| 	for r, i := range opts.Ignore { | 		return nil | ||||||
| 		opts.Ignore[r] = filepath.Clean(filepath.Join(opts.SrcContext, i)) |  | ||||||
| 	} | 	} | ||||||
| 	err := filepath.Walk(opts.SrcContext, func(path string, fi os.FileInfo, _ error) error { | 	ignore, err := dockerfile.ParseDockerignore(opts) | ||||||
| 		if ignoreFile(path) { | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	logrus.Infof("Removing ignored files from build context: %s", ignore) | ||||||
|  | 	for r, i := range ignore { | ||||||
|  | 		ignore[r] = filepath.Clean(filepath.Join(opts.SrcContext, i)) | ||||||
|  | 	} | ||||||
|  | 	err = filepath.Walk(opts.SrcContext, func(path string, fi os.FileInfo, _ error) error { | ||||||
|  | 		if ignoreFile(path, ignore) { | ||||||
| 			if err := os.RemoveAll(path); err != nil { | 			if err := os.RemoveAll(path); err != nil { | ||||||
| 				logrus.Debugf("error removing %s from buildcontext", path) | 				logrus.Debugf("error removing %s from buildcontext", path) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
|  | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | 	} | ||||||
|  | 	path := filepath.Join(opts.SrcContext, ".dockerignore") | ||||||
|  | 	return os.Remove(path) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func ignoreFile(path string) bool { | func ignoreFile(path string, ignore []string) bool { | ||||||
| 	for _, i := range opts.Ignore { | 	for _, i := range ignore { | ||||||
| 		matched, err := filepath.Match(i, path) | 		matched, err := filepath.Match(i, path) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return false | 			return false | ||||||
|  |  | ||||||
|  | @ -57,14 +57,6 @@ var argsMap = map[string][]string{ | ||||||
| 
 | 
 | ||||||
| var filesToIgnore = []string{"test/*"} | var filesToIgnore = []string{"test/*"} | ||||||
| 
 | 
 | ||||||
| func ignoreFlags() []string { |  | ||||||
| 	var f []string |  | ||||||
| 	for _, i := range filesToIgnore { |  | ||||||
| 		f = append(f, fmt.Sprintf("--ignore=%s", i)) |  | ||||||
| 	} |  | ||||||
| 	return f |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Arguments to build Dockerfiles with when building with docker
 | // Arguments to build Dockerfiles with when building with docker
 | ||||||
| var additionalDockerFlagsMap = map[string][]string{ | var additionalDockerFlagsMap = map[string][]string{ | ||||||
| 	"Dockerfile_test_target": {"--target=second"}, | 	"Dockerfile_test_target": {"--target=second"}, | ||||||
|  | @ -75,7 +67,6 @@ var additionalKanikoFlagsMap = map[string][]string{ | ||||||
| 	"Dockerfile_test_add":     {"--single-snapshot"}, | 	"Dockerfile_test_add":     {"--single-snapshot"}, | ||||||
| 	"Dockerfile_test_scratch": {"--single-snapshot"}, | 	"Dockerfile_test_scratch": {"--single-snapshot"}, | ||||||
| 	"Dockerfile_test_target":  {"--target=second"}, | 	"Dockerfile_test_target":  {"--target=second"}, | ||||||
| 	"Dockerfile_test_ignore":  ignoreFlags(), |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var bucketContextTests = []string{"Dockerfile_test_copy_bucket"} | var bucketContextTests = []string{"Dockerfile_test_copy_bucket"} | ||||||
|  | @ -125,7 +116,6 @@ type DockerFileBuilder struct { | ||||||
| 	FilesBuilt           map[string]bool | 	FilesBuilt           map[string]bool | ||||||
| 	DockerfilesToIgnore  map[string]struct{} | 	DockerfilesToIgnore  map[string]struct{} | ||||||
| 	TestCacheDockerfiles map[string]struct{} | 	TestCacheDockerfiles map[string]struct{} | ||||||
| 	TestIgnoreDockerfiles map[string]struct{} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewDockerFileBuilder will create a DockerFileBuilder initialized with dockerfiles, which
 | // NewDockerFileBuilder will create a DockerFileBuilder initialized with dockerfiles, which
 | ||||||
|  | @ -143,9 +133,6 @@ func NewDockerFileBuilder(dockerfiles []string) *DockerFileBuilder { | ||||||
| 		"Dockerfile_test_cache":         {}, | 		"Dockerfile_test_cache":         {}, | ||||||
| 		"Dockerfile_test_cache_install": {}, | 		"Dockerfile_test_cache_install": {}, | ||||||
| 	} | 	} | ||||||
| 	d.TestIgnoreDockerfiles = map[string]struct{}{ |  | ||||||
| 		"Dockerfile_test_ignore": {}, |  | ||||||
| 	} |  | ||||||
| 	return &d | 	return &d | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -174,29 +161,24 @@ func (d *DockerFileBuilder) BuildImage(imageRepo, gcsBucket, dockerfilesPath, do | ||||||
| 			"."}, | 			"."}, | ||||||
| 			additionalFlags...)..., | 			additionalFlags...)..., | ||||||
| 	) | 	) | ||||||
| 	if d.includeDockerIgnore(dockerfile) { |  | ||||||
| 	if err := setupTestDir(); err != nil { | 	if err := setupTestDir(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if err := generateDockerIgnore(); err != nil { | 	if err := generateDockerIgnore(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	_, err := RunCommandWithoutTest(dockerCmd) | 	_, err := RunCommandWithoutTest(dockerCmd) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("Failed to build image %s with docker command \"%s\": %s", dockerImage, dockerCmd.Args, err) | 		return fmt.Errorf("Failed to build image %s with docker command \"%s\": %s", dockerImage, dockerCmd.Args, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if d.includeDockerIgnore(dockerfilesPath) { |  | ||||||
| 		if err := deleteDockerIgnore(); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	if err := setupTestDir(); err != nil { | 	if err := setupTestDir(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	if err := generateDockerIgnore(); err != nil { | ||||||
|  | 		return err | ||||||
| 	} | 	} | ||||||
| 	defer removeTestDir() |  | ||||||
| 
 | 
 | ||||||
| 	contextFlag := "-c" | 	contextFlag := "-c" | ||||||
| 	contextPath := buildContextPath | 	contextPath := buildContextPath | ||||||
|  | @ -288,23 +270,10 @@ func (d *DockerFileBuilder) buildCachedImages(imageRepo, cacheRepo, dockerfilesP | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (d *DockerFileBuilder) includeDockerIgnore(dockerfile string) bool { |  | ||||||
| 	for i := range d.TestIgnoreDockerfiles { |  | ||||||
| 		if i == dockerfile { |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func setupTestDir() error { | func setupTestDir() error { | ||||||
| 	return os.MkdirAll(testDirPath, 0644) | 	return os.MkdirAll(testDirPath, 0644) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func removeTestDir() error { |  | ||||||
| 	return os.RemoveAll(testDirPath) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func generateDockerIgnore() error { | func generateDockerIgnore() error { | ||||||
| 	f, err := os.Create(".dockerignore") | 	f, err := os.Create(".dockerignore") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -317,7 +286,3 @@ func generateDockerIgnore() error { | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func deleteDockerIgnore() error { |  | ||||||
| 	return os.Remove(".dockerignore") |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ type KanikoOptions struct { | ||||||
| 	CacheDir       string | 	CacheDir       string | ||||||
| 	Destinations   multiArg | 	Destinations   multiArg | ||||||
| 	BuildArgs      multiArg | 	BuildArgs      multiArg | ||||||
| 	Ignore         multiArg |  | ||||||
| 	InsecurePush   bool | 	InsecurePush   bool | ||||||
| 	SkipTLSVerify  bool | 	SkipTLSVerify  bool | ||||||
| 	SingleSnapshot bool | 	SingleSnapshot bool | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"path/filepath" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
|  | @ -168,3 +169,23 @@ func saveStage(index int, stages []instructions.Stage) bool { | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // DockerignoreExists returns true if .dockerignore exists in the source context
 | ||||||
|  | func DockerignoreExists(opts *config.KanikoOptions) bool { | ||||||
|  | 	path := filepath.Join(opts.SrcContext, ".dockerignore") | ||||||
|  | 	return util.FilepathExists(path) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ParseDockerignore returns a list of all paths in .dockerignore
 | ||||||
|  | func ParseDockerignore(opts *config.KanikoOptions) ([]string, error) { | ||||||
|  | 	path := filepath.Join(opts.SrcContext, ".dockerignore") | ||||||
|  | 	contents, err := ioutil.ReadFile(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, errors.Wrap(err, "parsing .dockerignore") | ||||||
|  | 	} | ||||||
|  | 	return strings.FieldsFunc(string(contents), split), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func split(r rune) bool { | ||||||
|  | 	return r == '\n' || r == ' ' | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue