Skip to content

Commit

Permalink
docker build: accept -f - to read Dockerfile from stdin
Browse files Browse the repository at this point in the history
Implements proposal moby#27393 that describes the meaning of '-f -' in a
`docker build` command. For all context types except reading a context from
stdin, '-f -' will replace any file called 'Dockerfile' in the context's
tar stream with the contents of stdin. If the context itself is read from
stdin, '-f -' continues to read the Dockerfile called '-' from this context.

Fixes moby#27393.

Signed-off-by: David Sheets <sheets@alum.mit.edu>
  • Loading branch information
dsheets authored and David Sheets committed Feb 15, 2017
1 parent fe5f630 commit 664a01f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 10 deletions.
28 changes: 28 additions & 0 deletions cli/command/image/build.go
Expand Up @@ -6,10 +6,12 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"runtime"
"time"

"github.com/docker/distribution/reference"
"github.com/docker/docker/api"
Expand Down Expand Up @@ -167,6 +169,10 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
return fmt.Errorf("unable to prepare context: path %q not found", specifiedContext)
}

if options.dockerfileName == "-" {
relDockerfile = builder.DefaultDockerfileName
}

if err != nil {
if options.quiet && urlutil.IsURL(specifiedContext) {
fmt.Fprintln(dockerCli.Err(), progBuff)
Expand Down Expand Up @@ -232,6 +238,28 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
}
}

if options.dockerfileName == "-" && specifiedContext != "-" {
stdin := dockerCli.In()
file, err := ioutil.ReadAll(stdin)
stdin.Close()
if err != nil {
return err
}
now := time.Now()
fileHdr := tar.Header{
Name: builder.DefaultDockerfileName,
Mode: 0600,
Uid: 0,
Gid: 0,
Size: int64(len(file)),
ModTime: now,
Typeflag: tar.TypeReg,
AccessTime: now,
ChangeTime: now,
}
buildCtx = archive.ReplaceFileTarWrapper(buildCtx, fileHdr, file)
}

ctx := context.Background()

var resolvedTags []*resolvedTag
Expand Down
24 changes: 14 additions & 10 deletions cli/command/image/build/context.go
Expand Up @@ -165,7 +165,7 @@ func GetContextFromLocalDir(localDir, dockerfileName string) (absContextDir, rel
// When using a local context directory, when the Dockerfile is specified
// with the `-f/--file` option then it is considered relative to the
// current directory and not the context directory.
if dockerfileName != "" {
if dockerfileName != "" && dockerfileName != "-" {
if dockerfileName, err = filepath.Abs(dockerfileName); err != nil {
return "", "", fmt.Errorf("unable to get absolute path to Dockerfile: %v", err)
}
Expand Down Expand Up @@ -219,6 +219,8 @@ func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDi
absDockerfile = altPath
}
}
} else if absDockerfile == "-" {
absDockerfile = filepath.Join(absContextDir, DefaultDockerfileName)
}

// If not already an absolute path, the Dockerfile path should be joined to
Expand All @@ -233,18 +235,20 @@ func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDi
// an issue in golang. On Windows, EvalSymLinks does not work on UNC file
// paths (those starting with \\). This hack means that when using links
// on UNC paths, they will not be followed.
if !isUNC(absDockerfile) {
absDockerfile, err = filepath.EvalSymlinks(absDockerfile)
if err != nil {
return "", "", fmt.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err)
if givenDockerfile != "-" {
if !isUNC(absDockerfile) {
absDockerfile, err = filepath.EvalSymlinks(absDockerfile)
if err != nil {
return "", "", fmt.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err)
}
}
}

if _, err := os.Lstat(absDockerfile); err != nil {
if os.IsNotExist(err) {
return "", "", fmt.Errorf("Cannot locate Dockerfile: %q", absDockerfile)
if _, err := os.Lstat(absDockerfile); err != nil {
if os.IsNotExist(err) {
return "", "", fmt.Errorf("Cannot locate Dockerfile: %q", absDockerfile)
}
return "", "", fmt.Errorf("unable to stat Dockerfile: %v", err)
}
return "", "", fmt.Errorf("unable to stat Dockerfile: %v", err)
}

if relDockerfile, err = filepath.Rel(absContextDir, absDockerfile); err != nil {
Expand Down

0 comments on commit 664a01f

Please sign in to comment.