|
|
|
@ -20,17 +20,20 @@ import (
|
|
|
|
|
"github.com/docker/cli/cli"
|
|
|
|
|
"github.com/docker/cli/cli/command"
|
|
|
|
|
dockeropts "github.com/docker/cli/opts"
|
|
|
|
|
"github.com/docker/distribution/reference"
|
|
|
|
|
"github.com/docker/docker/pkg/ioutils"
|
|
|
|
|
"github.com/docker/go-units"
|
|
|
|
|
"github.com/moby/buildkit/client"
|
|
|
|
|
"github.com/moby/buildkit/session/auth/authprovider"
|
|
|
|
|
"github.com/moby/buildkit/solver/errdefs"
|
|
|
|
|
"github.com/moby/buildkit/util/appcontext"
|
|
|
|
|
"github.com/moby/buildkit/util/grpcerrors"
|
|
|
|
|
"github.com/morikuni/aec"
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const defaultTargetName = "default"
|
|
|
|
@ -44,6 +47,7 @@ type buildOptions struct {
|
|
|
|
|
cacheFrom []string
|
|
|
|
|
cacheTo []string
|
|
|
|
|
cgroupParent string
|
|
|
|
|
contexts []string
|
|
|
|
|
extraHosts []string
|
|
|
|
|
imageIDFile string
|
|
|
|
|
labels []string
|
|
|
|
@ -100,11 +104,17 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
|
|
|
|
|
in.progress = "quiet"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
contexts, err := parseContextNames(in.contexts)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
opts := build.Options{
|
|
|
|
|
Inputs: build.Inputs{
|
|
|
|
|
ContextPath: in.contextPath,
|
|
|
|
|
DockerfilePath: in.dockerfileName,
|
|
|
|
|
InStream: os.Stdin,
|
|
|
|
|
NamedContexts: contexts,
|
|
|
|
|
},
|
|
|
|
|
BuildArgs: listToMap(in.buildArgs, true),
|
|
|
|
|
ExtraHosts: in.extraHosts,
|
|
|
|
@ -209,6 +219,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imageID, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile)
|
|
|
|
|
err = wrapBuildError(err)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@ -339,6 +350,8 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
|
|
|
|
|
flags.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
|
|
|
|
|
flags.SetAnnotation("cgroup-parent", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#use-a-custom-parent-cgroup---cgroup-parent"})
|
|
|
|
|
|
|
|
|
|
flags.StringArrayVar(&options.contexts, "build-context", []string{}, "Additional build contexts (e.g., name=path)")
|
|
|
|
|
|
|
|
|
|
flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`)
|
|
|
|
|
flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"})
|
|
|
|
|
|
|
|
|
@ -462,3 +475,49 @@ func listToMap(values []string, defaultEnv bool) map[string]string {
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseContextNames(values []string) (map[string]string, error) {
|
|
|
|
|
if len(values) == 0 {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
result := make(map[string]string, len(values))
|
|
|
|
|
for _, value := range values {
|
|
|
|
|
kv := strings.SplitN(value, "=", 2)
|
|
|
|
|
if len(kv) != 2 {
|
|
|
|
|
return nil, errors.Errorf("invalid context value: %s, expected key=value", value)
|
|
|
|
|
}
|
|
|
|
|
named, err := reference.ParseNormalizedNamed(kv[0])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrapf(err, "invalid context name %s", kv[0])
|
|
|
|
|
}
|
|
|
|
|
name := strings.TrimSuffix(reference.FamiliarString(named), ":latest")
|
|
|
|
|
result[name] = kv[1]
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func wrapBuildError(err error) error {
|
|
|
|
|
if err == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
st, ok := grpcerrors.AsGRPCStatus(err)
|
|
|
|
|
if ok {
|
|
|
|
|
if st.Code() == codes.Unimplemented && strings.Contains(st.Message(), "unsupported frontend capability moby.buildkit.frontend.contexts") {
|
|
|
|
|
return &wrapped{err, "current frontend does not support --build-context. Named contexts are supported since Dockerfile v1.4"}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type wrapped struct {
|
|
|
|
|
err error
|
|
|
|
|
msg string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *wrapped) Error() string {
|
|
|
|
|
return w.msg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *wrapped) Unwrap() error {
|
|
|
|
|
return w.err
|
|
|
|
|
}
|
|
|
|
|