mirror of
https://github.com/docker/compose.git
synced 2026-10-12 02:13:08 +00:00
pkg/compose: align classic builder implementation with docker/cli
This aligns the implementation closer to the implementation in docker/cli, with the refactor done in [cli@260f1db]; this removes some direct uses of the github.com/docker/docker/builder/remotecontext/urlutil package, which won't be included in the new Moby modules. There's still some remaining uses in the `dockerFilePath` utility (which may need to be updated to also account for remote contexts that are not "git"), so possibly we can remove the use in that utility as well. [cli@260f1db]: https://github.com/docker/cli/commit/260f1dbebb9f3d70d2bdda67e511a6bee9fe365b Signed-off-by: Sebastiaan van Stijn <[email protected]>
This commit is contained in:
committed by
Nicolas De loof
parent
a03f2562df
commit
63920c4cc0
@@ -37,10 +37,10 @@ import (
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/image/build"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||
"github.com/moby/buildkit/client"
|
||||
gitutil "github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
|
||||
"github.com/moby/buildkit/util/progress/progressui"
|
||||
@@ -505,7 +505,7 @@ func dockerFilePath(ctxName string, dockerfile string) string {
|
||||
if dockerfile == "" {
|
||||
return ""
|
||||
}
|
||||
if urlutil.IsGitURL(ctxName) {
|
||||
if contextType, _ := build.DetectContextType(ctxName); contextType == build.ContextTypeGit {
|
||||
return dockerfile
|
||||
}
|
||||
if !filepath.IsAbs(dockerfile) {
|
||||
|
||||
@@ -34,7 +34,6 @@ import (
|
||||
buildtypes "github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
@@ -48,17 +47,9 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
buildCtx io.ReadCloser
|
||||
dockerfileCtx io.ReadCloser
|
||||
contextDir string
|
||||
tempDir string
|
||||
relDockerfile string
|
||||
|
||||
err error
|
||||
)
|
||||
|
||||
dockerfileName := dockerFilePath(service.Build.Context, service.Build.Dockerfile)
|
||||
specifiedContext := service.Build.Context
|
||||
progBuff := s.stdout()
|
||||
buildBuff := s.stdout()
|
||||
|
||||
if len(service.Build.Platforms) > 1 {
|
||||
return "", fmt.Errorf("the classic builder doesn't support multi-arch build, set DOCKER_BUILDKIT=1 to use BuildKit")
|
||||
}
|
||||
@@ -80,34 +71,51 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
}
|
||||
service.Build.Labels[api.ImageBuilderLabel] = "classic"
|
||||
|
||||
switch {
|
||||
case isLocalDir(specifiedContext):
|
||||
dockerfileName := dockerFilePath(service.Build.Context, service.Build.Dockerfile)
|
||||
specifiedContext := service.Build.Context
|
||||
progBuff := s.stdout()
|
||||
buildBuff := s.stdout()
|
||||
|
||||
contextType, err := build.DetectContextType(specifiedContext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch contextType {
|
||||
case build.ContextTypeStdin:
|
||||
return "", fmt.Errorf("building from STDIN is not supported")
|
||||
case build.ContextTypeLocal:
|
||||
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, dockerfileName)
|
||||
if err == nil && strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
|
||||
// Dockerfile is outside of build-context; read the Dockerfile and pass it as dockerfileCtx
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to prepare context: %w", err)
|
||||
}
|
||||
if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
|
||||
// Dockerfile is outside build-context; read the Dockerfile and pass it as dockerfileCtx
|
||||
dockerfileCtx, err = os.Open(dockerfileName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to open Dockerfile: %w", err)
|
||||
}
|
||||
defer dockerfileCtx.Close() //nolint:errcheck
|
||||
}
|
||||
case urlutil.IsGitURL(specifiedContext):
|
||||
case build.ContextTypeGit:
|
||||
var tempDir string
|
||||
tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, dockerfileName)
|
||||
case urlutil.IsURL(specifiedContext):
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to prepare context: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = os.RemoveAll(tempDir)
|
||||
}()
|
||||
contextDir = tempDir
|
||||
case build.ContextTypeRemote:
|
||||
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, specifiedContext, dockerfileName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to prepare context: %w", err)
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("unable to prepare context: path %q not found", specifiedContext)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to prepare context: %w", err)
|
||||
}
|
||||
|
||||
if tempDir != "" {
|
||||
defer os.RemoveAll(tempDir) //nolint:errcheck
|
||||
contextDir = tempDir
|
||||
}
|
||||
|
||||
// read from a directory into tar archive
|
||||
if buildCtx == nil {
|
||||
excludes, err := build.ReadDockerignore(contextDir)
|
||||
@@ -125,7 +133,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, false)
|
||||
buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
|
||||
ExcludePatterns: excludes,
|
||||
ChownOpts: &archive.ChownOpts{},
|
||||
ChownOpts: &archive.ChownOpts{UID: 0, GID: 0},
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -145,6 +153,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Setup an upload progress bar
|
||||
progressOutput := streamformatter.NewProgressOutput(progBuff)
|
||||
body := progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
|
||||
|
||||
@@ -166,16 +175,16 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
RegistryToken: authConfig.RegistryToken,
|
||||
}
|
||||
}
|
||||
buildOptions := imageBuildOptions(s.dockerCli, project, service, options)
|
||||
buildOpts := imageBuildOptions(s.dockerCli, project, service, options)
|
||||
imageName := api.GetImageNameOrDefault(service, project.Name)
|
||||
buildOptions.Tags = append(buildOptions.Tags, imageName)
|
||||
buildOptions.Dockerfile = relDockerfile
|
||||
buildOptions.AuthConfigs = authConfigs
|
||||
buildOptions.Memory = options.Memory
|
||||
buildOpts.Tags = append(buildOpts.Tags, imageName)
|
||||
buildOpts.Dockerfile = relDockerfile
|
||||
buildOpts.AuthConfigs = authConfigs
|
||||
buildOpts.Memory = options.Memory
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
response, err := s.apiClient().ImageBuild(ctx, body, buildOptions)
|
||||
response, err := s.apiClient().ImageBuild(ctx, body, buildOpts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -206,11 +215,6 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
return imageID, nil
|
||||
}
|
||||
|
||||
func isLocalDir(c string) bool {
|
||||
_, err := os.Stat(c)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func imageBuildOptions(dockerCli command.Cli, project *types.Project, service types.ServiceConfig, options api.BuildOptions) buildtypes.ImageBuildOptions {
|
||||
config := service.Build
|
||||
return buildtypes.ImageBuildOptions{
|
||||
|
||||
Reference in New Issue
Block a user