Procházet zdrojové kódy

Merge pull request #1474 from docker/build_windows

Nicolas De loof před 4 roky
rodič
revize
d67e8b9c51
3 změnil soubory, kde provedl 151 přidání a 21 odebrání
  1. 25 20
      cli/mobycli/exec.go
  2. 13 1
      local/compose/build.go
  3. 113 0
      local/compose/build_win.go

+ 25 - 20
cli/mobycli/exec.go

@@ -62,18 +62,40 @@ func mustDelegateToMoby(ctxType string) bool {
 
 // Exec delegates to com.docker.cli if on moby context
 func Exec(root *cobra.Command) {
+	childExit := make(chan bool)
+	err := RunDocker(childExit, os.Args[1:]...)
+	childExit <- true
+	if err != nil {
+		metrics.Track(store.DefaultContextType, os.Args[1:], metrics.FailureStatus)
+
+		if exiterr, ok := err.(*exec.ExitError); ok {
+			os.Exit(exiterr.ExitCode())
+		}
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	command := metrics.GetCommand(os.Args[1:])
+	if command == "build" {
+		utils.DisplayScanSuggestMsg()
+	}
+	metrics.Track(store.DefaultContextType, os.Args[1:], metrics.SuccessStatus)
+
+	os.Exit(0)
+}
+
+// RunDocker runs a docker command, and forward signals to the shellout command (stops listening to signals when an event is sent to childExit)
+func RunDocker(childExit chan bool, args ...string) error {
 	execBinary, err := resolvepath.LookPath(ComDockerCli)
 	if err != nil {
 		fmt.Fprintln(os.Stderr, err)
 		os.Exit(1)
 	}
-	cmd := exec.Command(execBinary, os.Args[1:]...)
+	cmd := exec.Command(execBinary, args...)
 	cmd.Stdin = os.Stdin
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
 
 	signals := make(chan os.Signal, 1)
-	childExit := make(chan bool)
 	signal.Notify(signals) // catch all signals
 	go func() {
 		for {
@@ -90,24 +112,7 @@ func Exec(root *cobra.Command) {
 		}
 	}()
 
-	err = cmd.Run()
-	childExit <- true
-	if err != nil {
-		metrics.Track(store.DefaultContextType, os.Args[1:], metrics.FailureStatus)
-
-		if exiterr, ok := err.(*exec.ExitError); ok {
-			os.Exit(exiterr.ExitCode())
-		}
-		fmt.Fprintln(os.Stderr, err)
-		os.Exit(1)
-	}
-	command := metrics.GetCommand(os.Args[1:])
-	if command == "build" {
-		utils.DisplayScanSuggestMsg()
-	}
-	metrics.Track(store.DefaultContextType, os.Args[1:], metrics.SuccessStatus)
-
-	os.Exit(0)
+	return cmd.Run()
 }
 
 // IsDefaultContextCommand checks if the command exists in the classic cli (issues a shellout --help)

+ 13 - 1
local/compose/build.go

@@ -41,6 +41,18 @@ import (
 func (s *composeService) Build(ctx context.Context, project *types.Project, options compose.BuildOptions) error {
 	opts := map[string]build.Options{}
 	imagesToBuild := []string{}
+
+	// retrieve OS type
+	info, err := s.apiClient.Info(ctx)
+	if err != nil {
+		return err
+	}
+	if info.OSType == "windows" {
+		// no support yet for Windows container builds in Buildkit
+		// https://docs.docker.com/develop/develop-images/build_enhancements/#limitations
+		return s.windowsBuild(project, options)
+	}
+
 	for _, service := range project.Services {
 		if service.Build != nil {
 			imageName := getImageName(service, project.Name)
@@ -66,7 +78,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
 		}
 	}
 
-	err := s.build(ctx, project, opts, options.Progress)
+	err = s.build(ctx, project, opts, options.Progress)
 	if err == nil {
 		if len(imagesToBuild) > 0 {
 			utils.DisplayScanSuggestMsg()

+ 113 - 0
local/compose/build_win.go

@@ -0,0 +1,113 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package compose
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/docker/compose-cli/api/compose"
+	"github.com/docker/compose-cli/cli/mobycli"
+
+	"github.com/compose-spec/compose-go/types"
+)
+
+func (s *composeService) windowsBuild(project *types.Project, options compose.BuildOptions) error {
+	projectDir := project.WorkingDir
+	for _, service := range project.Services {
+		if service.Build != nil {
+			imageName := getImageName(service, project.Name)
+			dockerfile := service.Build.Dockerfile
+			if dockerfile != "" {
+				if stat, err := os.Stat(projectDir); err == nil && stat.IsDir() {
+
+					dockerfile = filepath.Join(projectDir, dockerfile)
+				}
+			}
+			// build args
+			cmd := &commandBuilder{
+				Path: filepath.Join(projectDir, service.Build.Context),
+			}
+			cmd.addParams("--build-arg", options.Args)
+			cmd.addFlag("--pull", options.Pull)
+			cmd.addArg("--progress", options.Progress)
+
+			cmd.addList("--cache-from", service.Build.CacheFrom)
+			cmd.addArg("--file", dockerfile)
+			cmd.addParams("--label", service.Build.Labels)
+			cmd.addArg("--network", service.Build.Network)
+			cmd.addArg("--target", service.Build.Target)
+			cmd.addArg("--platform", service.Platform)
+			cmd.addArg("--isolation", service.Build.Isolation)
+			cmd.addList("--add-host", service.Build.ExtraHosts)
+
+			cmd.addArg("--tag", imageName)
+
+			args := cmd.getArguments()
+			// shell out to moby cli
+			childExit := make(chan bool)
+			err := mobycli.RunDocker(childExit, args...)
+			childExit <- true
+
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+type commandBuilder struct {
+	Args []string
+	Path string
+}
+
+func (c *commandBuilder) addArg(name, value string) {
+	if value != "" {
+		c.Args = append(c.Args, name, value)
+	}
+}
+
+func (c *commandBuilder) addFlag(name string, flag bool) {
+	if flag {
+		c.Args = append(c.Args, name)
+	}
+}
+
+func (c *commandBuilder) addParams(name string, params map[string]string) {
+	if len(params) > 0 {
+		for k, v := range params {
+			c.Args = append(c.Args, name, fmt.Sprintf("%s=%s", k, v))
+		}
+	}
+}
+
+func (c *commandBuilder) addList(name string, values []string) {
+	if len(values) > 0 {
+		for _, v := range values {
+			c.Args = append(c.Args, name, v)
+		}
+	}
+}
+
+func (c *commandBuilder) getArguments() []string {
+	cmd := []string{"build"}
+	cmd = append(cmd, c.Args...)
+	cmd = append(cmd, c.Path)
+	return cmd
+}