github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/builder/builder-next/controller.go (about)

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