github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/local/local.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package local 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 24 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 30 ) 31 32 // Build runs a docker build on the host and tags the resulting image with 33 // its checksum. It streams build progress to the writer argument. 34 func (b *Builder) Build(ctx context.Context, out io.Writer, a *latest.Artifact) build.ArtifactBuilder { 35 if b.prune { 36 b.localPruner.asynchronousCleanupOldImages(ctx, []string{a.ImageName}) 37 } 38 builder := build.WithLogFile(b.buildArtifact, b.muted) 39 return builder 40 } 41 42 func (b *Builder) PreBuild(_ context.Context, out io.Writer) error { 43 if b.localCluster { 44 output.Default.Fprintf(out, "Found [%s] context, using local docker daemon.\n", b.kubeContext) 45 } 46 return nil 47 } 48 49 func (b *Builder) PostBuild(ctx context.Context, _ io.Writer) error { 50 defer b.localDocker.Close() 51 if b.prune { 52 if b.mode == config.RunModes.Build { 53 b.localPruner.synchronousCleanupOldImages(ctx, b.builtImages) 54 } else { 55 b.localPruner.asynchronousCleanupOldImages(ctx, b.builtImages) 56 } 57 } 58 return nil 59 } 60 61 func (b *Builder) Concurrency() *int { return b.local.Concurrency } 62 63 func (b *Builder) PushImages() bool { 64 return b.pushImages 65 } 66 67 func (b *Builder) SupportedPlatforms() platform.Matcher { return platform.All } 68 69 func (b *Builder) buildArtifact(ctx context.Context, out io.Writer, a *latest.Artifact, tag string, platforms platform.Matcher) (string, error) { 70 digestOrImageID, err := b.runBuildForArtifact(ctx, out, a, tag, platforms) 71 if err != nil { 72 return "", err 73 } 74 75 if b.pushImages { 76 // only track images for pruning when building with docker 77 // if we're pushing a bazel image, it was built directly to the registry 78 if a.DockerArtifact != nil { 79 imageID, err := b.getImageIDForTag(ctx, tag) 80 if err != nil { 81 log.Entry(ctx).Warn("unable to inspect image: built images may not be cleaned up correctly by skaffold") 82 } 83 if imageID != "" { 84 b.builtImages = append(b.builtImages, imageID) 85 } 86 } 87 88 digest := digestOrImageID 89 return build.TagWithDigest(tag, digest), nil 90 } 91 92 imageID := digestOrImageID 93 b.builtImages = append(b.builtImages, imageID) 94 return build.TagWithImageID(ctx, tag, imageID, b.localDocker) 95 } 96 97 func (b *Builder) runBuildForArtifact(ctx context.Context, out io.Writer, a *latest.Artifact, tag string, platforms platform.Matcher) (string, error) { 98 if !b.pushImages { 99 // All of the builders will rely on a local Docker: 100 // + Either to build the image, 101 // + Or to docker load it. 102 // Let's fail fast if Docker is not available 103 if _, err := b.localDocker.ServerVersion(ctx); err != nil { 104 return "", err 105 } 106 } 107 108 builder, err := newPerArtifactBuilder(b, a) 109 if err != nil { 110 return "", err 111 } 112 if platforms.IsNotEmpty() { 113 supported := builder.SupportedPlatforms() 114 if p := platforms.Intersect(supported); p.IsNotEmpty() { 115 platforms = p 116 } else { 117 return "", fmt.Errorf("builder for artifact %q doesn't support building for target platforms: %q. Supported platforms are %q", a.ImageName, platforms, supported) 118 } 119 } 120 return builder.Build(ctx, out, a, tag, platforms) 121 } 122 123 func (b *Builder) getImageIDForTag(ctx context.Context, tag string) (string, error) { 124 insp, _, err := b.localDocker.ImageInspectWithRaw(ctx, tag) 125 if err != nil { 126 return "", err 127 } 128 return insp.ID, nil 129 } 130 131 func (b *Builder) retrieveExtraEnv() []string { 132 return b.localDocker.ExtraEnv() 133 }