github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/builder/builder-next/controller.go (about) 1 package buildkit 2 3 import ( 4 "context" 5 "net/http" 6 "os" 7 "path/filepath" 8 9 "github.com/containerd/containerd/content/local" 10 ctdmetadata "github.com/containerd/containerd/metadata" 11 "github.com/containerd/containerd/platforms" 12 "github.com/containerd/containerd/snapshots" 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/filters" 15 "github.com/docker/docker/builder/builder-next/adapters/containerimage" 16 "github.com/docker/docker/builder/builder-next/adapters/localinlinecache" 17 "github.com/docker/docker/builder/builder-next/adapters/snapshot" 18 containerimageexp "github.com/docker/docker/builder/builder-next/exporter" 19 "github.com/docker/docker/builder/builder-next/imagerefchecker" 20 mobyworker "github.com/docker/docker/builder/builder-next/worker" 21 "github.com/docker/docker/daemon/config" 22 "github.com/docker/docker/daemon/graphdriver" 23 units "github.com/docker/go-units" 24 "github.com/moby/buildkit/cache" 25 "github.com/moby/buildkit/cache/metadata" 26 "github.com/moby/buildkit/cache/remotecache" 27 inlineremotecache "github.com/moby/buildkit/cache/remotecache/inline" 28 localremotecache "github.com/moby/buildkit/cache/remotecache/local" 29 "github.com/moby/buildkit/client" 30 "github.com/moby/buildkit/control" 31 "github.com/moby/buildkit/frontend" 32 dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder" 33 "github.com/moby/buildkit/frontend/gateway" 34 "github.com/moby/buildkit/frontend/gateway/forwarder" 35 containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" 36 "github.com/moby/buildkit/solver/bboltcachestorage" 37 "github.com/moby/buildkit/util/archutil" 38 "github.com/moby/buildkit/util/entitlements" 39 "github.com/moby/buildkit/util/leaseutil" 40 "github.com/moby/buildkit/worker" 41 specs "github.com/opencontainers/image-spec/specs-go/v1" 42 "github.com/pkg/errors" 43 bolt "go.etcd.io/bbolt" 44 ) 45 46 func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) { 47 if err := os.MkdirAll(opt.Root, 0711); err != nil { 48 return nil, err 49 } 50 51 dist := opt.Dist 52 root := opt.Root 53 54 var driver graphdriver.Driver 55 if ls, ok := dist.LayerStore.(interface { 56 Driver() graphdriver.Driver 57 }); ok { 58 driver = ls.Driver() 59 } else { 60 return nil, errors.Errorf("could not access graphdriver") 61 } 62 63 store, err := local.NewStore(filepath.Join(root, "content")) 64 if err != nil { 65 return nil, err 66 } 67 68 db, err := bolt.Open(filepath.Join(root, "containerdmeta.db"), 0644, nil) 69 if err != nil { 70 return nil, errors.WithStack(err) 71 } 72 73 mdb := ctdmetadata.NewDB(db, store, map[string]snapshots.Snapshotter{}) 74 75 store = containerdsnapshot.NewContentStore(mdb.ContentStore(), "buildkit") 76 77 lm := leaseutil.WithNamespace(ctdmetadata.NewLeaseManager(mdb), "buildkit") 78 79 snapshotter, lm, err := snapshot.NewSnapshotter(snapshot.Opt{ 80 GraphDriver: driver, 81 LayerStore: dist.LayerStore, 82 Root: root, 83 IdentityMapping: opt.IdentityMapping, 84 }, lm) 85 if err != nil { 86 return nil, err 87 } 88 89 if err := cache.MigrateV2(context.Background(), filepath.Join(root, "metadata.db"), filepath.Join(root, "metadata_v2.db"), store, snapshotter, lm); err != nil { 90 return nil, err 91 } 92 93 md, err := metadata.NewStore(filepath.Join(root, "metadata_v2.db")) 94 if err != nil { 95 return nil, err 96 } 97 98 layerGetter, ok := snapshotter.(imagerefchecker.LayerGetter) 99 if !ok { 100 return nil, errors.Errorf("snapshotter does not implement layergetter") 101 } 102 103 refChecker := imagerefchecker.New(imagerefchecker.Opt{ 104 ImageStore: dist.ImageStore, 105 LayerGetter: layerGetter, 106 }) 107 108 cm, err := cache.NewManager(cache.ManagerOpt{ 109 Snapshotter: snapshotter, 110 MetadataStore: md, 111 PruneRefChecker: refChecker, 112 LeaseManager: lm, 113 ContentStore: store, 114 GarbageCollect: mdb.GarbageCollect, 115 }) 116 if err != nil { 117 return nil, err 118 } 119 120 src, err := containerimage.NewSource(containerimage.SourceOpt{ 121 CacheAccessor: cm, 122 ContentStore: store, 123 DownloadManager: dist.DownloadManager, 124 MetadataStore: dist.V2MetadataService, 125 ImageStore: dist.ImageStore, 126 ReferenceStore: dist.ReferenceStore, 127 RegistryHosts: opt.RegistryHosts, 128 LayerStore: dist.LayerStore, 129 LeaseManager: lm, 130 GarbageCollect: mdb.GarbageCollect, 131 }) 132 if err != nil { 133 return nil, err 134 } 135 136 dns := getDNSConfig(opt.DNSConfig) 137 138 exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, dns, opt.Rootless, opt.IdentityMapping, opt.ApparmorProfile) 139 if err != nil { 140 return nil, err 141 } 142 143 differ, ok := snapshotter.(containerimageexp.Differ) 144 if !ok { 145 return nil, errors.Errorf("snapshotter doesn't support differ") 146 } 147 148 exp, err := containerimageexp.New(containerimageexp.Opt{ 149 ImageStore: dist.ImageStore, 150 ReferenceStore: dist.ReferenceStore, 151 Differ: differ, 152 }) 153 if err != nil { 154 return nil, err 155 } 156 157 cacheStorage, err := bboltcachestorage.NewStore(filepath.Join(opt.Root, "cache.db")) 158 if err != nil { 159 return nil, err 160 } 161 162 gcPolicy, err := getGCPolicy(opt.BuilderConfig, root) 163 if err != nil { 164 return nil, errors.Wrap(err, "could not get builder GC policy") 165 } 166 167 layers, ok := snapshotter.(mobyworker.LayerAccess) 168 if !ok { 169 return nil, errors.Errorf("snapshotter doesn't support differ") 170 } 171 172 p, err := parsePlatforms(archutil.SupportedPlatforms(true)) 173 if err != nil { 174 return nil, err 175 } 176 177 leases, err := lm.List(context.TODO(), "labels.\"buildkit/lease.temporary\"") 178 if err != nil { 179 return nil, err 180 } 181 for _, l := range leases { 182 lm.Delete(context.TODO(), l) 183 } 184 185 wopt := mobyworker.Opt{ 186 ID: "moby", 187 MetadataStore: md, 188 ContentStore: store, 189 CacheManager: cm, 190 GCPolicy: gcPolicy, 191 Snapshotter: snapshotter, 192 Executor: exec, 193 ImageSource: src, 194 DownloadManager: dist.DownloadManager, 195 V2MetadataService: dist.V2MetadataService, 196 Exporter: exp, 197 Transport: rt, 198 Layers: layers, 199 Platforms: p, 200 } 201 202 wc := &worker.Controller{} 203 w, err := mobyworker.NewWorker(wopt) 204 if err != nil { 205 return nil, err 206 } 207 wc.Add(w) 208 209 frontends := map[string]frontend.Frontend{ 210 "dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build), 211 "gateway.v0": gateway.NewGatewayFrontend(wc), 212 } 213 214 return control.NewController(control.Opt{ 215 SessionManager: opt.SessionManager, 216 WorkerController: wc, 217 Frontends: frontends, 218 CacheKeyStorage: cacheStorage, 219 ResolveCacheImporterFuncs: map[string]remotecache.ResolveCacheImporterFunc{ 220 "registry": localinlinecache.ResolveCacheImporterFunc(opt.SessionManager, opt.RegistryHosts, store, dist.ReferenceStore, dist.ImageStore), 221 "local": localremotecache.ResolveCacheImporterFunc(opt.SessionManager), 222 }, 223 ResolveCacheExporterFuncs: map[string]remotecache.ResolveCacheExporterFunc{ 224 "inline": inlineremotecache.ResolveCacheExporterFunc(), 225 }, 226 Entitlements: getEntitlements(opt.BuilderConfig), 227 }) 228 } 229 230 func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, error) { 231 var gcPolicy []client.PruneInfo 232 if conf.GC.Enabled { 233 var ( 234 defaultKeepStorage int64 235 err error 236 ) 237 238 if conf.GC.DefaultKeepStorage != "" { 239 defaultKeepStorage, err = units.RAMInBytes(conf.GC.DefaultKeepStorage) 240 if err != nil { 241 return nil, errors.Wrapf(err, "could not parse '%s' as Builder.GC.DefaultKeepStorage config", conf.GC.DefaultKeepStorage) 242 } 243 } 244 245 if conf.GC.Policy == nil { 246 gcPolicy = mobyworker.DefaultGCPolicy(root, defaultKeepStorage) 247 } else { 248 gcPolicy = make([]client.PruneInfo, len(conf.GC.Policy)) 249 for i, p := range conf.GC.Policy { 250 b, err := units.RAMInBytes(p.KeepStorage) 251 if err != nil { 252 return nil, err 253 } 254 if b == 0 { 255 b = defaultKeepStorage 256 } 257 gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{ 258 All: p.All, 259 KeepStorage: b, 260 Filters: filters.Args(p.Filter), 261 }) 262 if err != nil { 263 return nil, err 264 } 265 } 266 } 267 } 268 return gcPolicy, nil 269 } 270 271 func parsePlatforms(platformsStr []string) ([]specs.Platform, error) { 272 out := make([]specs.Platform, 0, len(platformsStr)) 273 for _, s := range platformsStr { 274 p, err := platforms.Parse(s) 275 if err != nil { 276 return nil, err 277 } 278 out = append(out, platforms.Normalize(p)) 279 } 280 return out, nil 281 } 282 283 func getEntitlements(conf config.BuilderConfig) []string { 284 var ents []string 285 // Incase of no config settings, NetworkHost should be enabled & SecurityInsecure must be disabled. 286 if conf.Entitlements.NetworkHost == nil || *conf.Entitlements.NetworkHost { 287 ents = append(ents, string(entitlements.EntitlementNetworkHost)) 288 } 289 if conf.Entitlements.SecurityInsecure != nil && *conf.Entitlements.SecurityInsecure { 290 ents = append(ents, string(entitlements.EntitlementSecurityInsecure)) 291 } 292 return ents 293 }