Extract dockerfile handling functions.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2017-04-16 15:01:15 -04:00
parent 59983759c2
commit b98e03d3b0
3 changed files with 47 additions and 33 deletions

View File

@ -8,7 +8,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"regexp" "regexp"
"runtime" "runtime"
"time" "time"
@ -20,10 +19,8 @@ import (
"github.com/docker/docker/api" "github.com/docker/docker/api"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder/dockerignore"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/streamformatter"
@ -208,22 +205,13 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
} }
if buildCtx == nil { if buildCtx == nil {
f, err := os.Open(filepath.Join(contextDir, ".dockerignore")) excludes, err := build.ReadDockerignore(contextDir)
if err != nil && !os.IsNotExist(err) {
return err
}
defer f.Close()
var excludes []string
if err == nil {
excludes, err = dockerignore.ReadAll(f)
if err != nil { if err != nil {
return err return err
} }
}
if err := build.ValidateContextDirectory(contextDir, excludes); err != nil { if err := build.ValidateContextDirectory(contextDir, excludes); err != nil {
return errors.Errorf("Error checking context: '%s'.", err) return errors.Errorf("error checking context: '%s'.", err)
} }
// And canonicalize dockerfile name to a platform-independent one // And canonicalize dockerfile name to a platform-independent one
@ -232,20 +220,7 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
return errors.Errorf("cannot canonicalize dockerfile path %s: %v", relDockerfile, err) return errors.Errorf("cannot canonicalize dockerfile path %s: %v", relDockerfile, err)
} }
// If .dockerignore mentions .dockerignore or the Dockerfile then make excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, options.dockerfileFromStdin())
// sure we send both files over to the daemon because Dockerfile is,
// obviously, needed no matter what, and .dockerignore is needed to know
// if either one needs to be removed. The daemon will remove them
// if necessary, after it parses the Dockerfile. Ignore errors here, as
// they will have been caught by validateContextDirectory above.
// Excludes are used instead of includes to maintain the order of files
// in the archive.
if keep, _ := fileutils.Matches(".dockerignore", excludes); keep {
excludes = append(excludes, "!.dockerignore")
}
if keep, _ := fileutils.Matches(relDockerfile, excludes); keep && !options.dockerfileFromStdin() {
excludes = append(excludes, "!"+relDockerfile)
}
compression := archive.Uncompressed compression := archive.Uncompressed
if options.compress { if options.compress {

View File

@ -143,7 +143,7 @@ func GetContextFromGitURL(gitURL, dockerfileName string) (string, string, error)
return "", "", errors.Wrapf(err, "unable to 'git clone' to temporary context directory") return "", "", errors.Wrapf(err, "unable to 'git clone' to temporary context directory")
} }
absContextDir, err = resolveAndValidateContextPath(absContextDir) absContextDir, err = ResolveAndValidateContextPath(absContextDir)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -173,7 +173,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
// the relative path of the dockerfile in that context directory, and a non-nil // the relative path of the dockerfile in that context directory, and a non-nil
// error on success. // error on success.
func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, error) { func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, error) {
localDir, err := resolveAndValidateContextPath(localDir) localDir, err := ResolveAndValidateContextPath(localDir)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -191,9 +191,9 @@ func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, er
return localDir, relDockerfile, err return localDir, relDockerfile, err
} }
// resolveAndValidateContextPath uses the given context directory for a `docker build` // ResolveAndValidateContextPath uses the given context directory for a `docker build`
// and returns the absolute path to the context directory. // and returns the absolute path to the context directory.
func resolveAndValidateContextPath(givenContextDir string) (string, error) { func ResolveAndValidateContextPath(givenContextDir string) (string, error) {
absContextDir, err := filepath.Abs(givenContextDir) absContextDir, err := filepath.Abs(givenContextDir)
if err != nil { if err != nil {
return "", errors.Errorf("unable to get absolute context directory of given context directory %q: %v", givenContextDir, err) return "", errors.Errorf("unable to get absolute context directory of given context directory %q: %v", givenContextDir, err)

View File

@ -0,0 +1,39 @@
package build
import (
"os"
"path/filepath"
"github.com/docker/docker/builder/dockerignore"
"github.com/docker/docker/pkg/fileutils"
)
// ReadDockerignore reads the .dockerignore file in the context directory and
// returns the list of paths to exclude
func ReadDockerignore(contextDir string) ([]string, error) {
var excludes []string
f, err := os.Open(filepath.Join(contextDir, ".dockerignore"))
switch {
case os.IsNotExist(err):
return excludes, nil
case err != nil:
return nil, err
}
defer f.Close()
return dockerignore.ReadAll(f)
}
// TrimBuildFilesFromExcludes removes the named Dockerfile and .dockerignore from
// the list of excluded files. The daemon will remove them from the final context
// but they must be in available in the context when passed to the API.
func TrimBuildFilesFromExcludes(excludes []string, dockerfile string, dockerfileFromStdin bool) []string {
if keep, _ := fileutils.Matches(".dockerignore", excludes); keep {
excludes = append(excludes, "!.dockerignore")
}
if keep, _ := fileutils.Matches(dockerfile, excludes); keep && !dockerfileFromStdin {
excludes = append(excludes, "!"+dockerfile)
}
return excludes
}