Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build-base-alpine
ENV GOTOOLCHAIN=local
COPY --link --from=xx / /
RUN apk add --no-cache bash clang lld llvm file git
RUN apk add --no-cache bash clang lld llvm file git git-daemon
WORKDIR /go/src/github.com/docker/cli

FROM build-base-alpine AS build-alpine
Expand Down
68 changes: 32 additions & 36 deletions cli/command/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
buildtypes "github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/moby/go-archive"
Expand Down Expand Up @@ -76,12 +75,6 @@ func (o buildOptions) dockerfileFromStdin() bool {
return o.dockerfileName == "-"
}

// contextFromStdin returns true when the user specified that the build context
// should be read from stdin
func (o buildOptions) contextFromStdin() bool {
return o.context == "-"
}

func newBuildOptions() buildOptions {
ulimits := make(map[string]*container.Ulimit)
return buildOptions{
Expand Down Expand Up @@ -189,21 +182,24 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
buildCtx io.ReadCloser
dockerfileCtx io.ReadCloser
contextDir string
tempDir string
relDockerfile string
progBuff io.Writer
buildBuff io.Writer
remote string
)

contextType, err := build.DetectContextType(options.context)
if err != nil {
return err
}

if options.dockerfileFromStdin() {
if options.contextFromStdin() {
if contextType == build.ContextTypeStdin {
return errors.New("invalid argument: can't use stdin for both build context and dockerfile")
}
dockerfileCtx = dockerCli.In()
}

specifiedContext := options.context
progBuff = dockerCli.Out()
buildBuff = dockerCli.Out()
if options.quiet {
Expand All @@ -217,38 +213,43 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
}
}

switch {
case options.contextFromStdin():
switch contextType {
case build.ContextTypeStdin:
// buildCtx is tar archive. if stdin was dockerfile then it is wrapped
buildCtx, relDockerfile, err = build.GetContextFromReader(dockerCli.In(), options.dockerfileName)
case isLocalDir(specifiedContext):
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, options.dockerfileName)
if err == nil && strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
if err != nil {
return fmt.Errorf("unable to prepare context from STDIN: %w", err)
}
case build.ContextTypeLocal:
contextDir, relDockerfile, err = build.GetContextFromLocalDir(options.context, options.dockerfileName)
if err != nil {
return errors.Errorf("unable to prepare context: %s", err)
}
if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
// Dockerfile is outside of build-context; read the Dockerfile and pass it as dockerfileCtx
dockerfileCtx, err = os.Open(options.dockerfileName)
if err != nil {
return errors.Errorf("unable to open Dockerfile: %v", err)
}
defer dockerfileCtx.Close()
}
case urlutil.IsGitURL(specifiedContext):
tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, options.dockerfileName)
case urlutil.IsURL(specifiedContext):
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, specifiedContext, options.dockerfileName)
default:
return errors.Errorf("unable to prepare context: path %q not found", specifiedContext)
}

if err != nil {
if options.quiet && urlutil.IsURL(specifiedContext) {
_, _ = fmt.Fprintln(dockerCli.Err(), progBuff)
case build.ContextTypeGit:
var tempDir string
tempDir, relDockerfile, err = build.GetContextFromGitURL(options.context, options.dockerfileName)
if err != nil {
return errors.Errorf("unable to prepare context: %s", err)
}
return errors.Errorf("unable to prepare context: %s", err)
}

if tempDir != "" {
defer os.RemoveAll(tempDir)
defer func() {
_ = os.RemoveAll(tempDir)
}()
contextDir = tempDir
case build.ContextTypeRemote:
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, options.context, options.dockerfileName)
if err != nil && options.quiet {
_, _ = fmt.Fprintln(dockerCli.Err(), progBuff)
}
default:
return errors.Errorf("unable to prepare context: path %q not found", options.context)
}

// read from a directory into tar archive
Expand Down Expand Up @@ -415,11 +416,6 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
return nil
}

func isLocalDir(c string) bool {
_, err := os.Stat(c)
return err == nil
}

type translatorFunc func(context.Context, reference.NamedTagged) (reference.Canonical, error)

// validateTag checks if the given image name can be resolved.
Expand Down
2 changes: 1 addition & 1 deletion cli/command/image/build/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"strings"
"time"

"github.com/docker/docker/builder/remotecontext/git"
"github.com/docker/cli/cli/command/image/build/internal/git"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/moby/go-archive"
Expand Down
39 changes: 39 additions & 0 deletions cli/command/image/build/context_detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package build

import (
"fmt"
"os"

"github.com/docker/cli/cli/command/image/build/internal/urlutil"
)

// ContextType describes the type (source) of build-context specified.
type ContextType string

const (
ContextTypeStdin ContextType = "stdin" // ContextTypeStdin indicates that the build-context is a TAR archive passed through STDIN.
ContextTypeLocal ContextType = "local" // ContextTypeLocal indicates that the build-context is a local directory.
ContextTypeRemote ContextType = "remote" // ContextTypeRemote indicates that the build-context is a remote URL.
ContextTypeGit ContextType = "git" // ContextTypeGit indicates that the build-context is a GIT URL.
)

// DetectContextType detects the type (source) of the build-context.
func DetectContextType(specifiedContext string) (ContextType, error) {
switch {
case specifiedContext == "-":
return ContextTypeStdin, nil
case isLocalDir(specifiedContext):
return ContextTypeLocal, nil
case urlutil.IsGitURL(specifiedContext):
return ContextTypeGit, nil
case urlutil.IsURL(specifiedContext):
return ContextTypeRemote, nil
default:
return "", fmt.Errorf("unable to prepare context: path %q not found", specifiedContext)
}
}

func isLocalDir(c string) bool {
_, err := os.Stat(c)
return err == nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ func supportsShallowClone(remoteURL string) bool {

// Try a HEAD request and fallback to a Get request on error
res, err := http.Head(serviceURL) // #nosec G107
if err == nil {
_ = res.Body.Close()
}
if err != nil || res.StatusCode != http.StatusOK {
res, err = http.Get(serviceURL) // #nosec G107
if err == nil {
Expand Down
Loading
Loading