build: fix `-f` handling with buildkit

This commit brings a more pedantic change in the following ambiguous case:
cat Dockerfile | docker build -f otherDockerfile -

The legacy builder does not error out and prefers the Dockerfile from stdin
while the buildkit-based one errors out.

Note that this is only in the case where stdin is a Dockerfile (not an archive)

Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
Tibor Vass 2018-05-23 06:15:11 +00:00
parent 89e102474c
commit 82f0e1e5d8
1 changed files with 45 additions and 37 deletions

View File

@ -31,6 +31,8 @@ import (
const uploadRequestRemote = "upload-request" const uploadRequestRemote = "upload-request"
var errDockerfileConflict = errors.New("ambiguous Dockerfile source: both stdin and flag correspond to Dockerfiles")
func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error { func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
ctx := appcontext.Context() ctx := appcontext.Context()
@ -45,10 +47,14 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
buildID := stringid.GenerateRandomID() buildID := stringid.GenerateRandomID()
var ( var (
remote string remote string
body io.Reader body io.Reader
dockerfileName = filepath.Base(options.dockerfileName) dockerfileName = options.dockerfileName
dockerfileReader io.ReadCloser
dockerfileDir string
contextDir string
) )
switch { switch {
case options.contextFromStdin(): case options.contextFromStdin():
if options.dockerfileFromStdin() { if options.dockerfileFromStdin() {
@ -62,46 +68,25 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
body = rc body = rc
remote = uploadRequestRemote remote = uploadRequestRemote
} else { } else {
dockerfileDir, err := build.WriteTempDockerfile(rc) if options.dockerfileName != "" {
if err != nil { return errDockerfileConflict
return err
} }
defer os.RemoveAll(dockerfileDir) dockerfileReader = rc
emptyDir, _ := ioutil.TempDir("", "stupid-empty-dir")
defer os.RemoveAll(emptyDir)
s.Allow(filesync.NewFSSyncProvider([]filesync.SyncedDir{
{
Name: "context",
Dir: emptyDir,
},
{
Name: "dockerfile",
Dir: dockerfileDir,
},
}))
remote = clientSessionRemote remote = clientSessionRemote
// TODO: make fssync handle empty contextdir
contextDir, _ = ioutil.TempDir("", "empty-dir")
defer os.RemoveAll(contextDir)
} }
case isLocalDir(options.context): case isLocalDir(options.context):
dockerfileDir := filepath.Dir(options.dockerfileName) contextDir = options.context
if options.dockerfileFromStdin() { if options.dockerfileFromStdin() {
dockerfileDir, err = build.WriteTempDockerfile(os.Stdin) dockerfileReader = os.Stdin
if err != nil { } else if options.dockerfileName != "" {
return err dockerfileName = filepath.Base(options.dockerfileName)
} dockerfileDir = filepath.Dir(options.dockerfileName)
defer os.RemoveAll(dockerfileDir) } else {
dockerfileName = build.DefaultDockerfileName dockerfileDir = options.context
} }
s.Allow(filesync.NewFSSyncProvider([]filesync.SyncedDir{
{
Name: "context",
Dir: options.context,
Map: resetUIDAndGID,
},
{
Name: "dockerfile",
Dir: dockerfileDir,
},
}))
remote = clientSessionRemote remote = clientSessionRemote
case urlutil.IsGitURL(options.context): case urlutil.IsGitURL(options.context):
remote = options.context remote = options.context
@ -111,6 +96,29 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
return errors.Errorf("unable to prepare context: path %q not found", options.context) return errors.Errorf("unable to prepare context: path %q not found", options.context)
} }
if dockerfileReader != nil {
dockerfileName = build.DefaultDockerfileName
dockerfileDir, err = build.WriteTempDockerfile(dockerfileReader)
if err != nil {
return err
}
defer os.RemoveAll(dockerfileDir)
}
if dockerfileDir != "" {
s.Allow(filesync.NewFSSyncProvider([]filesync.SyncedDir{
{
Name: "context",
Dir: contextDir,
Map: resetUIDAndGID,
},
{
Name: "dockerfile",
Dir: dockerfileDir,
},
}))
}
// statusContext, cancelStatus := context.WithCancel(ctx) // statusContext, cancelStatus := context.WithCancel(ctx)
// defer cancelStatus() // defer cancelStatus()