diff --git a/components/engine/cli/command/image/build.go b/components/engine/cli/command/image/build.go index f6984619c1..965acb4b51 100644 --- a/components/engine/cli/command/image/build.go +++ b/components/engine/cli/command/image/build.go @@ -247,46 +247,10 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error { // replace Dockerfile if added dynamically if dockerfileCtx != nil { - file, err := ioutil.ReadAll(dockerfileCtx) - dockerfileCtx.Close() + buildCtx, relDockerfile, err = addDockerfileToBuildContext(dockerfileCtx, buildCtx) if err != nil { return err } - now := time.Now() - hdrTmpl := &tar.Header{ - Mode: 0600, - Uid: 0, - Gid: 0, - ModTime: now, - Typeflag: tar.TypeReg, - AccessTime: now, - ChangeTime: now, - } - randomName := ".dockerfile." + stringid.GenerateRandomID()[:20] - - buildCtx = archive.ReplaceFileTarWrapper(buildCtx, map[string]archive.TarModifierFunc{ - randomName: func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { - return hdrTmpl, file, nil - }, - ".dockerignore": func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { - if h == nil { - h = hdrTmpl - } - extraIgnore := randomName + "\n" - b := &bytes.Buffer{} - if content != nil { - _, err := b.ReadFrom(content) - if err != nil { - return nil, nil, err - } - } else { - extraIgnore += ".dockerignore\n" - } - b.Write([]byte("\n" + extraIgnore)) - return h, b.Bytes(), nil - }, - }) - relDockerfile = randomName } ctx := context.Background() @@ -392,6 +356,51 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error { return nil } +func addDockerfileToBuildContext(dockerfileCtx io.ReadCloser, buildCtx io.ReadCloser) (io.ReadCloser, string, error) { + file, err := ioutil.ReadAll(dockerfileCtx) + dockerfileCtx.Close() + if err != nil { + return nil, "", err + } + now := time.Now() + hdrTmpl := &tar.Header{ + Mode: 0600, + Uid: 0, + Gid: 0, + ModTime: now, + Typeflag: tar.TypeReg, + AccessTime: now, + ChangeTime: now, + } + randomName := ".dockerfile." + stringid.GenerateRandomID()[:20] + + buildCtx = archive.ReplaceFileTarWrapper(buildCtx, map[string]archive.TarModifierFunc{ + // Add the dockerfile with a random filename + randomName: func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { + return hdrTmpl, file, nil + }, + // Update .dockerignore to include the random filename + ".dockerignore": func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { + if h == nil { + h = hdrTmpl + } + extraIgnore := randomName + "\n" + b := &bytes.Buffer{} + if content != nil { + _, err := b.ReadFrom(content) + if err != nil { + return nil, nil, err + } + } else { + extraIgnore += ".dockerignore\n" + } + b.Write([]byte("\n" + extraIgnore)) + return h, b.Bytes(), nil + }, + }) + return buildCtx, randomName, nil +} + func isLocalDir(c string) bool { _, err := os.Stat(c) return err == nil diff --git a/components/engine/pkg/archive/archive.go b/components/engine/pkg/archive/archive.go index 53f35037d1..3fb1ca4ca2 100644 --- a/components/engine/pkg/archive/archive.go +++ b/components/engine/pkg/archive/archive.go @@ -230,10 +230,8 @@ func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, er // define a modification step for a single path type TarModifierFunc func(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) -// ReplaceFileTarWrapper converts inputTarStream to a new tar stream -// while replacing a single file called header.Name with new contents. -// If the file with header.Name does not exist it is added to the tar stream. -// TODO: make this into a generic tar conversion function with walkFn argument +// ReplaceFileTarWrapper converts inputTarStream to a new tar stream. Files in the +// tar stream are modified if they match any of the keys in mods. func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModifierFunc) io.ReadCloser { pipeReader, pipeWriter := io.Pipe() @@ -255,7 +253,7 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi for len(modKeys) > 0 && (err == io.EOF || err == nil && hdr.Name >= modKeys[0]) { var h *tar.Header var rdr io.Reader - if hdr != nil && hdr.Name == modKeys[0] { + if err == nil && hdr != nil && hdr.Name == modKeys[0] { h = hdr rdr = tarReader }