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