mirror of https://github.com/docker/cli.git
build: remove --stream
--stream was always experimental and this patch removes the functionality. Users should enable BuildKit with DOCKER_BUILDKIT=1 Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
parent
47fd8986ea
commit
c3990f3ba6
|
@ -10,7 +10,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -33,7 +32,6 @@ import (
|
||||||
"github.com/docker/docker/pkg/urlutil"
|
"github.com/docker/docker/pkg/urlutil"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -165,9 +163,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
flags.SetAnnotation("squash", "version", []string{"1.25"})
|
flags.SetAnnotation("squash", "version", []string{"1.25"})
|
||||||
|
|
||||||
flags.BoolVar(&options.stream, "stream", false, "Stream attaches to server to negotiate build context")
|
flags.BoolVar(&options.stream, "stream", false, "Stream attaches to server to negotiate build context")
|
||||||
flags.SetAnnotation("stream", "experimental", nil)
|
flags.MarkHidden("stream")
|
||||||
flags.SetAnnotation("stream", "version", []string{"1.31"})
|
|
||||||
flags.SetAnnotation("stream", "no-buildkit", nil)
|
|
||||||
|
|
||||||
flags.StringVar(&options.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
|
flags.StringVar(&options.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
|
||||||
flags.SetAnnotation("progress", "buildkit", nil)
|
flags.SetAnnotation("progress", "buildkit", nil)
|
||||||
|
@ -224,8 +220,8 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
remote string
|
remote string
|
||||||
)
|
)
|
||||||
|
|
||||||
if options.compress && options.stream {
|
if options.stream {
|
||||||
return errors.New("--compress conflicts with --stream options")
|
return errors.New("Experimental flag --stream was removed, enable BuildKit instead with DOCKER_BUILDKIT=1")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.dockerfileFromStdin() {
|
if options.dockerfileFromStdin() {
|
||||||
|
@ -284,7 +280,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read from a directory into tar archive
|
// read from a directory into tar archive
|
||||||
if buildCtx == nil && !options.stream {
|
if buildCtx == nil {
|
||||||
excludes, err := build.ReadDockerignore(contextDir)
|
excludes, err := build.ReadDockerignore(contextDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -315,16 +311,6 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if streaming and Dockerfile was not from stdin then read from file
|
|
||||||
// to the same reader that is usually stdin
|
|
||||||
if options.stream && dockerfileCtx == nil {
|
|
||||||
dockerfileCtx, err = os.Open(relDockerfile)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to open %s", relDockerfile)
|
|
||||||
}
|
|
||||||
defer dockerfileCtx.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -367,38 +353,11 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
buildCtx = dockerfileCtx
|
buildCtx = dockerfileCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := trySession(dockerCli, contextDir, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var body io.Reader
|
var body io.Reader
|
||||||
if buildCtx != nil && !options.stream {
|
if buildCtx != nil {
|
||||||
body = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
|
body = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
|
||||||
}
|
}
|
||||||
|
|
||||||
// add context stream to the session
|
|
||||||
if options.stream && s != nil {
|
|
||||||
syncDone := make(chan error) // used to signal first progress reporting completed.
|
|
||||||
// progress would also send errors but don't need it here as errors
|
|
||||||
// are handled by session.Run() and ImageBuild()
|
|
||||||
if err := addDirToSession(s, contextDir, progressOutput, syncDone); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := newBufferedWriter(syncDone, buildBuff)
|
|
||||||
defer func() {
|
|
||||||
select {
|
|
||||||
case <-buf.flushed:
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
buildBuff = buf
|
|
||||||
|
|
||||||
remote = clientSessionRemote
|
|
||||||
body = buildCtx
|
|
||||||
}
|
|
||||||
|
|
||||||
configFile := dockerCli.ConfigFile()
|
configFile := dockerCli.ConfigFile()
|
||||||
creds, _ := configFile.GetAllCredentials()
|
creds, _ := configFile.GetAllCredentials()
|
||||||
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
||||||
|
@ -411,20 +370,6 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
buildOptions.AuthConfigs = authConfigs
|
buildOptions.AuthConfigs = authConfigs
|
||||||
buildOptions.RemoteContext = remote
|
buildOptions.RemoteContext = remote
|
||||||
|
|
||||||
if s != nil {
|
|
||||||
go func() {
|
|
||||||
logrus.Debugf("running session: %v", s.ID())
|
|
||||||
dialSession := func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
|
|
||||||
return dockerCli.Client().DialHijack(ctx, "/session", proto, meta)
|
|
||||||
}
|
|
||||||
if err := s.Run(ctx, dialSession); err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
cancel() // cancel progress context
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
buildOptions.SessionID = s.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := dockerCli.Client().ImageBuild(ctx, body, buildOptions)
|
response, err := dockerCli.Client().ImageBuild(ctx, body, buildOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if options.quiet {
|
if options.quiet {
|
||||||
|
|
|
@ -1,28 +1,20 @@
|
||||||
package image
|
package image
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/image/build"
|
|
||||||
cliconfig "github.com/docker/cli/cli/config"
|
cliconfig "github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/pkg/progress"
|
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/session/filesync"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/time/rate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const clientSessionRemote = "client-session"
|
const clientSessionRemote = "client-session"
|
||||||
|
@ -49,87 +41,6 @@ func trySession(dockerCli command.Cli, contextDir string, forStream bool) (*sess
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDirToSession(session *session.Session, contextDir string, progressOutput progress.Output, done chan error) error {
|
|
||||||
excludes, err := build.ReadDockerignore(contextDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p := &sizeProgress{out: progressOutput, action: "Streaming build context to Docker daemon"}
|
|
||||||
|
|
||||||
workdirProvider := filesync.NewFSSyncProvider([]filesync.SyncedDir{
|
|
||||||
{Dir: contextDir, Excludes: excludes},
|
|
||||||
})
|
|
||||||
session.Allow(workdirProvider)
|
|
||||||
|
|
||||||
// this will be replaced on parallel build jobs. keep the current
|
|
||||||
// progressbar for now
|
|
||||||
if snpc, ok := workdirProvider.(interface {
|
|
||||||
SetNextProgressCallback(func(int, bool), chan error)
|
|
||||||
}); ok {
|
|
||||||
snpc.SetNextProgressCallback(p.update, done)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type sizeProgress struct {
|
|
||||||
out progress.Output
|
|
||||||
action string
|
|
||||||
limiter *rate.Limiter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *sizeProgress) update(size int, last bool) {
|
|
||||||
if sp.limiter == nil {
|
|
||||||
sp.limiter = rate.NewLimiter(rate.Every(100*time.Millisecond), 1)
|
|
||||||
}
|
|
||||||
if last || sp.limiter.Allow() {
|
|
||||||
sp.out.WriteProgress(progress.Progress{Action: sp.action, Current: int64(size), LastUpdate: last})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type bufferedWriter struct {
|
|
||||||
done chan error
|
|
||||||
io.Writer
|
|
||||||
buf *bytes.Buffer
|
|
||||||
flushed chan struct{}
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBufferedWriter(done chan error, w io.Writer) *bufferedWriter {
|
|
||||||
bw := &bufferedWriter{done: done, Writer: w, buf: new(bytes.Buffer), flushed: make(chan struct{})}
|
|
||||||
go func() {
|
|
||||||
<-done
|
|
||||||
bw.flushBuffer()
|
|
||||||
}()
|
|
||||||
return bw
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bw *bufferedWriter) Write(dt []byte) (int, error) {
|
|
||||||
select {
|
|
||||||
case <-bw.done:
|
|
||||||
bw.flushBuffer()
|
|
||||||
return bw.Writer.Write(dt)
|
|
||||||
default:
|
|
||||||
return bw.buf.Write(dt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bw *bufferedWriter) flushBuffer() {
|
|
||||||
bw.mu.Lock()
|
|
||||||
select {
|
|
||||||
case <-bw.flushed:
|
|
||||||
default:
|
|
||||||
bw.Writer.Write(bw.buf.Bytes())
|
|
||||||
close(bw.flushed)
|
|
||||||
}
|
|
||||||
bw.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bw *bufferedWriter) String() string {
|
|
||||||
return fmt.Sprintf("%s", bw.Writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBuildSharedKey(dir string) (string, error) {
|
func getBuildSharedKey(dir string) (string, error) {
|
||||||
// build session is hash of build dir with node based randomness
|
// build session is hash of build dir with node based randomness
|
||||||
s := sha256.Sum256([]byte(fmt.Sprintf("%s:%s", tryNodeIdentifier(), dir)))
|
s := sha256.Sum256([]byte(fmt.Sprintf("%s:%s", tryNodeIdentifier(), dir)))
|
||||||
|
|
|
@ -2873,11 +2873,6 @@ _docker_image_build() {
|
||||||
boolean_options+="
|
boolean_options+="
|
||||||
--compress
|
--compress
|
||||||
"
|
"
|
||||||
if __docker_server_is_experimental ; then
|
|
||||||
boolean_options+="
|
|
||||||
--stream
|
|
||||||
"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local all_options="$options_with_args $boolean_options"
|
local all_options="$options_with_args $boolean_options"
|
||||||
|
|
Loading…
Reference in New Issue