controller.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package buildkit
  2. import (
  3. "net/http"
  4. "os"
  5. "path/filepath"
  6. "github.com/containerd/containerd/content/local"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/builder/builder-next/adapters/containerimage"
  9. "github.com/docker/docker/builder/builder-next/adapters/snapshot"
  10. containerimageexp "github.com/docker/docker/builder/builder-next/exporter"
  11. "github.com/docker/docker/builder/builder-next/imagerefchecker"
  12. mobyworker "github.com/docker/docker/builder/builder-next/worker"
  13. "github.com/docker/docker/daemon/config"
  14. "github.com/docker/docker/daemon/graphdriver"
  15. units "github.com/docker/go-units"
  16. "github.com/moby/buildkit/cache"
  17. "github.com/moby/buildkit/cache/metadata"
  18. "github.com/moby/buildkit/cache/remotecache"
  19. inlineremotecache "github.com/moby/buildkit/cache/remotecache/inline"
  20. registryremotecache "github.com/moby/buildkit/cache/remotecache/registry"
  21. "github.com/moby/buildkit/client"
  22. "github.com/moby/buildkit/control"
  23. "github.com/moby/buildkit/frontend"
  24. dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder"
  25. "github.com/moby/buildkit/frontend/gateway"
  26. "github.com/moby/buildkit/frontend/gateway/forwarder"
  27. "github.com/moby/buildkit/snapshot/blobmapping"
  28. "github.com/moby/buildkit/solver/bboltcachestorage"
  29. "github.com/moby/buildkit/worker"
  30. "github.com/pkg/errors"
  31. )
  32. func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
  33. if err := os.MkdirAll(opt.Root, 0700); err != nil {
  34. return nil, err
  35. }
  36. dist := opt.Dist
  37. root := opt.Root
  38. var driver graphdriver.Driver
  39. if ls, ok := dist.LayerStore.(interface {
  40. Driver() graphdriver.Driver
  41. }); ok {
  42. driver = ls.Driver()
  43. } else {
  44. return nil, errors.Errorf("could not access graphdriver")
  45. }
  46. sbase, err := snapshot.NewSnapshotter(snapshot.Opt{
  47. GraphDriver: driver,
  48. LayerStore: dist.LayerStore,
  49. Root: root,
  50. })
  51. if err != nil {
  52. return nil, err
  53. }
  54. store, err := local.NewStore(filepath.Join(root, "content"))
  55. if err != nil {
  56. return nil, err
  57. }
  58. store = &contentStoreNoLabels{store}
  59. md, err := metadata.NewStore(filepath.Join(root, "metadata.db"))
  60. if err != nil {
  61. return nil, err
  62. }
  63. snapshotter := blobmapping.NewSnapshotter(blobmapping.Opt{
  64. Content: store,
  65. Snapshotter: sbase,
  66. MetadataStore: md,
  67. })
  68. layerGetter, ok := sbase.(imagerefchecker.LayerGetter)
  69. if !ok {
  70. return nil, errors.Errorf("snapshotter does not implement layergetter")
  71. }
  72. refChecker := imagerefchecker.New(imagerefchecker.Opt{
  73. ImageStore: dist.ImageStore,
  74. LayerGetter: layerGetter,
  75. })
  76. cm, err := cache.NewManager(cache.ManagerOpt{
  77. Snapshotter: snapshotter,
  78. MetadataStore: md,
  79. PruneRefChecker: refChecker,
  80. })
  81. if err != nil {
  82. return nil, err
  83. }
  84. src, err := containerimage.NewSource(containerimage.SourceOpt{
  85. CacheAccessor: cm,
  86. ContentStore: store,
  87. DownloadManager: dist.DownloadManager,
  88. MetadataStore: dist.V2MetadataService,
  89. ImageStore: dist.ImageStore,
  90. ReferenceStore: dist.ReferenceStore,
  91. ResolverOpt: opt.ResolverOpt,
  92. })
  93. if err != nil {
  94. return nil, err
  95. }
  96. exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, opt.Rootless)
  97. if err != nil {
  98. return nil, err
  99. }
  100. differ, ok := sbase.(containerimageexp.Differ)
  101. if !ok {
  102. return nil, errors.Errorf("snapshotter doesn't support differ")
  103. }
  104. exp, err := containerimageexp.New(containerimageexp.Opt{
  105. ImageStore: dist.ImageStore,
  106. ReferenceStore: dist.ReferenceStore,
  107. Differ: differ,
  108. })
  109. if err != nil {
  110. return nil, err
  111. }
  112. cacheStorage, err := bboltcachestorage.NewStore(filepath.Join(opt.Root, "cache.db"))
  113. if err != nil {
  114. return nil, err
  115. }
  116. gcPolicy, err := getGCPolicy(opt.BuilderConfig, root)
  117. if err != nil {
  118. return nil, errors.Wrap(err, "could not get builder GC policy")
  119. }
  120. layers, ok := sbase.(mobyworker.LayerAccess)
  121. if !ok {
  122. return nil, errors.Errorf("snapshotter doesn't support differ")
  123. }
  124. wopt := mobyworker.Opt{
  125. ID: "moby",
  126. MetadataStore: md,
  127. ContentStore: store,
  128. CacheManager: cm,
  129. GCPolicy: gcPolicy,
  130. Snapshotter: snapshotter,
  131. Executor: exec,
  132. ImageSource: src,
  133. DownloadManager: dist.DownloadManager,
  134. V2MetadataService: dist.V2MetadataService,
  135. Exporter: exp,
  136. Transport: rt,
  137. Layers: layers,
  138. }
  139. wc := &worker.Controller{}
  140. w, err := mobyworker.NewWorker(wopt)
  141. if err != nil {
  142. return nil, err
  143. }
  144. wc.Add(w)
  145. frontends := map[string]frontend.Frontend{
  146. "dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build),
  147. "gateway.v0": gateway.NewGatewayFrontend(wc),
  148. }
  149. return control.NewController(control.Opt{
  150. SessionManager: opt.SessionManager,
  151. WorkerController: wc,
  152. Frontends: frontends,
  153. CacheKeyStorage: cacheStorage,
  154. ResolveCacheImporterFuncs: map[string]remotecache.ResolveCacheImporterFunc{
  155. "registry": registryremotecache.ResolveCacheImporterFunc(opt.SessionManager, opt.ResolverOpt),
  156. },
  157. ResolveCacheExporterFuncs: map[string]remotecache.ResolveCacheExporterFunc{
  158. "inline": inlineremotecache.ResolveCacheExporterFunc(),
  159. },
  160. })
  161. }
  162. func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, error) {
  163. var gcPolicy []client.PruneInfo
  164. if conf.GC.Enabled {
  165. var (
  166. defaultKeepStorage int64
  167. err error
  168. )
  169. if conf.GC.DefaultKeepStorage != "" {
  170. defaultKeepStorage, err = units.RAMInBytes(conf.GC.DefaultKeepStorage)
  171. if err != nil {
  172. return nil, errors.Wrapf(err, "could not parse '%s' as Builder.GC.DefaultKeepStorage config", conf.GC.DefaultKeepStorage)
  173. }
  174. }
  175. if conf.GC.Policy == nil {
  176. gcPolicy = mobyworker.DefaultGCPolicy(root, defaultKeepStorage)
  177. } else {
  178. gcPolicy = make([]client.PruneInfo, len(conf.GC.Policy))
  179. for i, p := range conf.GC.Policy {
  180. b, err := units.RAMInBytes(p.KeepStorage)
  181. if err != nil {
  182. return nil, err
  183. }
  184. if b == 0 {
  185. b = defaultKeepStorage
  186. }
  187. gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{
  188. All: p.All,
  189. KeepStorage: b,
  190. Filters: p.Filter,
  191. })
  192. if err != nil {
  193. return nil, err
  194. }
  195. }
  196. }
  197. }
  198. return gcPolicy, nil
  199. }