Docker镜像服务image.Store

镜像服务是镜像操作的抽象接口,实际上对镜像的操作包含两部分,镜像信息和镜像数据;镜像服务基于镜像持久化服务image.StoreBackend提供的接口实现镜像信息的操作,通过镜像层服务image.LayerGetReleaser提供的镜像层操作的的操作,因为镜像都是由镜像层组成,也就是实际操作镜像数据。他们之间的关系大概如下:
这里写图片描述
接着我们先看下镜像服务,镜像持久化服务和镜像层服务的接口定义
在文件docker\image\store.go的镜像服务和镜像层服务接口:

// Store is an interface for creating and accessing images
type Store interface {
    Create(config []byte) (ID, error)
    Get(id ID) (*Image, error)
    Delete(id ID) ([]layer.Metadata, error)
    Search(partialID string) (ID, error)
    SetParent(id ID, parent ID) error
    GetParent(id ID) (ID, error)
    Children(id ID) []ID
    Map() map[ID]*Image
    Heads() map[ID]*Image
}

// LayerGetReleaser is a minimal interface for getting and releasing images.
//实现在docker/layer/layer_store.go
type LayerGetReleaser interface {
    Get(layer.ChainID) (layer.Layer, error)
    Release(layer.Layer) ([]layer.Metadata, error)
}

在文件docker\image\fs.go的镜像持久化服务接口:

type StoreBackend interface {
    Walk(f DigestWalkFunc) error
    Get(id digest.Digest) ([]byte, error)
    Set(data []byte) (digest.Digest, error)
    Delete(id digest.Digest) error
    SetMetadata(id digest.Digest, key string, data []byte) error
    GetMetadata(id digest.Digest, key string) ([]byte, error)
    DeleteMetadata(id digest.Digest, key string) error
}

基本上就是增删改查之类的功能,再看下镜像服务的实现类store和返回该类对象的工厂函数NewImageStore:

type imageMeta struct {
    layer    layer.Layer
    children map[ID]struct{}
}

type store struct {
    sync.Mutex
    ls        LayerGetReleaser
    images    map[ID]*imageMeta
    fs        StoreBackend
    digestSet *digest.Set
}

// NewImageStore returns new store object for given layer store
func NewImageStore(fs StoreBackend, ls LayerGetReleaser) (Store, error) {
    is := &store{
        //实现在/docker/layer/layer_store.go
        ls:        ls,
        images:    make(map[ID]*imageMeta),
        fs:        fs,
        digestSet: digest.NewSet(),
    }

    // load all current images and retain layers
    if err := is.restore(); err != nil {
        return nil, err
    }

    return is, nil
}

可以看到镜像服务实现类store成员中包含了镜像持久化服务image.StoreBackend和镜像层服务image.LayerGetReleaser,在而且两者是工厂函数的参数,工厂函数利用两个阐述参数传入的对象实现两个成员的初始化。所以我们还需要看下,镜像持久化服务image.StoreBackend和镜像层服务image.LayerGetReleaser的实现类。
镜像持久化服务image.StoreBackend实现类以及工厂函数,在docker\image\fs.go:

// fs implements StoreBackend using the filesystem.
type fs struct {
    sync.RWMutex
    root string
}

const (
    contentDirName  = "content"
    metadataDirName = "metadata"
)

// NewFSStoreBackend returns new filesystem based backend for image.Store
func NewFSStoreBackend(root string) (StoreBackend, error) {
    //传入镜像的存储位置  "/var/lib/docker/image/(graphDriver名)/imagedb"
    return newFSStore(root)
}

func newFSStore(root string) (*fs, error) {
    s := &fs{
        root: root,
    }
    if err := os.MkdirAll(filepath.Join(root, contentDirName, string(digest.Canonical)), 0700); err != nil {
        return nil, err
    }
    if err := os.MkdirAll(filepath.Join(root, metadataDirName, string(digest.Canonical)), 0700); err != nil {
        return nil, err
    }
    return s, nil
}

镜像层服务image.LayerGetReleaser实现类以及工厂函数,实现在docker\layer\layer_store.go:

type layerStore struct {
    store  MetadataStore
    driver graphdriver.Driver

    layerMap map[ChainID]*roLayer
    layerL   sync.Mutex

    mounts map[string]*mountedLayer
    mountL sync.Mutex
}

// StoreOptions are the options used to create a new Store instance
type StoreOptions struct {
    StorePath                 string
    MetadataStorePathTemplate string
    GraphDriver               string
    GraphDriverOptions        []string
    UIDMaps                   []idtools.IDMap
    GIDMaps                   []idtools.IDMap
    PluginGetter              getter.PluginGetter
}

// NewStoreFromOptions creates a new Store instance
//没有实现RegisterWithDescriptor接口
func NewStoreFromOptions(options StoreOptions) (Store, error) {
    driver, err := graphdriver.New(
        options.StorePath,
        options.GraphDriver,
        options.GraphDriverOptions,
        options.UIDMaps,
        options.GIDMaps,
        options.PluginGetter)
    if err != nil {
        return nil, fmt.Errorf("error initializing graphdriver: %v", err)
    }
    logrus.Debugf("Using graph driver %s", driver)
    logrus.Debugf("StorePath :%s", options.StorePath)

    fms, err := NewFSMetadataStore(fmt.Sprintf(options.MetadataStorePathTemplate, driver))
    if err != nil {
        return nil, err
    }

    return NewStoreFromGraphDriver(fms, driver)
}

// NewStoreFromGraphDriver creates a new Store instance using the provided
// metadata store and graph driver. The metadata store will be used to restore
// the Store.

看下他们是如何联系在一起的,这都是在docker\daemon\daemon.go的NewDaemon函数中处理的,看下函数调用过程:
这里写图片描述
看NewDaemon函数的代码片段:

    graphDriver := d.layerStore.DriverName()
    //镜像的存储位置"/var/lib/docker/image/(graphDriver名)"
    imageRoot := filepath.Join(config.Root, "image", graphDriver)

    // Configure and validate the kernels security support
    if err := configureKernelSecuritySupport(config, graphDriver); err != nil {
        return nil, err
    }

    logrus.Debugf("Max Concurrent Downloads: %d", *config.MaxConcurrentDownloads)
    d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, *config.MaxConcurrentDownloads)

    logrus.Debugf("Max Concurrent Uploads: %d", *config.MaxConcurrentUploads)
    d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads)
        //传入镜像的存储位置  "/var/lib/docker/image/(graphDriver名)/imagedb"
    ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb"))
    if err != nil {
        return nil, err
    }

在执行NewFSStoreBackend时,传入镜像信息的存储位置config.Root+/image/(graphDriver名)/imagedb,config.Root默认为/var/lib/docker,也就是镜像信息存储位置为”/var/lib/docker/image/(graphDriver名)/imagedb”:
在文件docker\daemon\config.go的InstallCommonFlags函数:

flags.StringVarP(&config.Root, "graph", "g", defaultGraph, "Root of the Docker runtime")

以及docker\daemon\config_unix.go:

var (
    defaultPidFile  = "/var/run/docker.pid"
    defaultGraph    = "/var/lib/docker"
    defaultExecRoot = "/var/run/docker"
)

如我启用的存储驱动为overlay,存储位置为”/var/lib/docker/image/overlay/imagedb”:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值