Skip to content

Commit

Permalink
Merge pull request moby#5 from rumpl/feat-pull
Browse files Browse the repository at this point in the history
Create the containerd image service
  • Loading branch information
rumpl committed Jul 5, 2022
2 parents 684f2fb + 413813d commit 5d0eaf6
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 33 deletions.
65 changes: 37 additions & 28 deletions cmd/dockerd/daemon.go
Expand Up @@ -234,7 +234,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
routerOptions.api = cli.api
routerOptions.cluster = c

initRouter(routerOptions)
initRouter(d, routerOptions)

go d.ProcessClusterNotifications(ctx, c.GetWatchStream())

Expand Down Expand Up @@ -291,34 +291,39 @@ func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, e
return opts, err
}
cgroupParent := newCgroupParent(config)
bk, err := buildkit.New(buildkit.Opt{
SessionManager: sm,
Root: filepath.Join(config.Root, "buildkit"),
Dist: d.DistributionServices(),
NetworkController: d.NetworkController(),
DefaultCgroupParent: cgroupParent,
RegistryHosts: d.RegistryHosts(),
BuilderConfig: config.Builder,
Rootless: d.Rootless(),
IdentityMapping: d.IdentityMapping(),
DNSConfig: config.DNSConfig,
ApparmorProfile: daemon.DefaultApparmorProfile(),
})
if err != nil {
return opts, err
}

bb, err := buildbackend.NewBackend(d.ImageService(), manager, bk, d.EventsService)
if err != nil {
return opts, errors.Wrap(err, "failed to create buildmanager")
}
return routerOptions{
ro := routerOptions{
sessionManager: sm,
buildBackend: bb,
buildkit: bk,
features: d.Features(),
daemon: d,
}, nil
}
if !d.UsesSnapshotter() {
bk, err := buildkit.New(buildkit.Opt{
SessionManager: sm,
Root: filepath.Join(config.Root, "buildkit"),
Dist: d.DistributionServices(),
NetworkController: d.NetworkController(),
DefaultCgroupParent: cgroupParent,
RegistryHosts: d.RegistryHosts(),
BuilderConfig: config.Builder,
Rootless: d.Rootless(),
IdentityMapping: d.IdentityMapping(),
DNSConfig: config.DNSConfig,
ApparmorProfile: daemon.DefaultApparmorProfile(),
})
if err != nil {
return opts, err
}

bb, err := buildbackend.NewBackend(d.ImageService(), manager, bk, d.EventsService)
if err != nil {
return opts, errors.Wrap(err, "failed to create buildmanager")
}

ro.buildBackend = bb
ro.buildkit = bk
}

return ro, nil
}

func (cli *DaemonCli) reloadConfig() {
Expand Down Expand Up @@ -521,7 +526,7 @@ func checkDeprecatedOptions(config *config.Config) error {
return nil
}

func initRouter(opts routerOptions) {
func initRouter(d *daemon.Daemon, opts routerOptions) {
decoder := runconfig.ContainerDecoder{
GetSysInfo: func() *sysinfo.SysInfo {
return opts.daemon.RawSysInfo()
Expand All @@ -548,7 +553,11 @@ func initRouter(opts routerOptions) {
}

grpcBackends := []grpcrouter.Backend{}
for _, b := range []interface{}{opts.daemon, opts.buildBackend} {
backends := []interface{}{opts.daemon}
if !d.UsesSnapshotter() {
backends = append(backends, opts.buildBackend)
}
for _, b := range backends {
if b, ok := b.(grpcrouter.Backend); ok {
grpcBackends = append(grpcBackends, b)
}
Expand Down
244 changes: 244 additions & 0 deletions daemon/containerd/service.go
@@ -0,0 +1,244 @@
package containerd

import (
"context"
"io"

"github.com/containerd/containerd"
"github.com/containerd/containerd/platforms"
"github.com/docker/distribution"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/filters"
imagetype "github.com/docker/docker/api/types/image"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/builder"
"github.com/docker/docker/container"
"github.com/docker/docker/daemon/images"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

type containerdStore struct {
client *containerd.Client
}

func NewService(c *containerd.Client) *containerdStore {
return &containerdStore{
client: c,
}
}

func (cs *containerdStore) PullImage(ctx context.Context, image, tag string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
var opts []containerd.RemoteOpt
if platform != nil {
opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
}
ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return errdefs.InvalidParameter(err)
}

if tag != "" {
// The "tag" could actually be a digest.
var dgst digest.Digest
dgst, err = digest.Parse(tag)
if err == nil {
ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
} else {
ref, err = reference.WithTag(ref, tag)
}
if err != nil {
return errdefs.InvalidParameter(err)
}
}

_, err = cs.client.Pull(ctx, ref.String(), opts...)
return err
}

func (cs *containerdStore) Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error) {
images, err := cs.client.ListImages(ctx)
if err != nil {
return nil, err
}

var ret []*types.ImageSummary
for _, image := range images {
size, err := image.Size(ctx)
if err != nil {
return nil, err
}

ret = append(ret, &types.ImageSummary{
RepoDigests: []string{image.Name() + "@" + image.Target().Digest.String()}, // "hello-world@sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38"},
RepoTags: []string{image.Name()},
Containers: -1,
ParentID: "",
SharedSize: -1,
VirtualSize: 10,
ID: image.Target().Digest.String(),
Created: image.Metadata().CreatedAt.Unix(),
Size: size,
})
}

return ret, nil
}

func (cs *containerdStore) LogImageEvent(imageID, refName, action string) {
panic("not implemented")
}

func (cs *containerdStore) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) {
panic("not implemented")
}

func (cs *containerdStore) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
panic("not implemented")
}

func (cs *containerdStore) Map() map[image.ID]*image.Image {
panic("not implemented")
}

func (cs *containerdStore) GetLayerByID(string) (layer.RWLayer, error) {
panic("not implemented")
}

func (cs *containerdStore) GetLayerMountID(string) (string, error) {
panic("not implemented")
}

func (cs *containerdStore) Cleanup() error {
return nil
}

func (cs *containerdStore) GraphDriverName() string {
return ""
}

func (cs *containerdStore) CommitBuildStep(c backend.CommitConfig) (image.ID, error) {
panic("not implemented")
}

func (cs *containerdStore) CreateImage(config []byte, parent string) (builder.Image, error) {
panic("not implemented")
}

func (cs *containerdStore) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
panic("not implemented")
}

func (cs *containerdStore) MakeImageCache(sourceRefs []string) builder.ImageCache {
panic("not implemented")
}

func (cs *containerdStore) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
panic("not implemented")
}

func (cs *containerdStore) SquashImage(id, parent string) (string, error) {
panic("not implemented")
}

func (cs *containerdStore) ExportImage(names []string, outStream io.Writer) error {
panic("not implemented")
}

func (cs *containerdStore) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error) {
panic("not implemented")
}

func (cs *containerdStore) ImageHistory(name string) ([]*imagetype.HistoryResponseItem, error) {
panic("not implemented")
}

func (cs *containerdStore) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
panic("not implemented")
}

func (cs *containerdStore) ImportImage(src string, repository string, platform *ocispec.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
panic("not implemented")
}

func (cs *containerdStore) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error {
panic("not implemented")
}

func (cs *containerdStore) LookupImage(ctx context.Context, name string) (*types.ImageInspect, error) {
panic("not implemented")
}

func (cs *containerdStore) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
panic("not implemented")
}

func (cs *containerdStore) SearchRegistryForImages(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registrytypes.SearchResults, error) {
panic("not implemented")
}

func (cs *containerdStore) TagImage(imageName, repository, tag string) (string, error) {
panic("not implemented")
}

func (cs *containerdStore) GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error) {
panic("not implemented")
}

func (cs *containerdStore) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
panic("not implemented")
}

func (cs *containerdStore) LayerDiskUsage(ctx context.Context) (int64, error) {
panic("not implemented")
}

func (cs *containerdStore) ReleaseLayer(rwlayer layer.RWLayer) error {
panic("not implemented")
}

func (cs *containerdStore) CommitImage(c backend.CommitConfig) (image.ID, error) {
panic("not implemented")
}

func (cs *containerdStore) GetImage(refOrID string, platform *ocispec.Platform) (retImg *image.Image, retErr error) {
panic("not implemented")
}

func (cs *containerdStore) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) {
panic("not implemented")
}

func (cs *containerdStore) DistributionServices() images.DistributionServices {
return images.DistributionServices{}
}

func (cs *containerdStore) CountImages() int {
imgs, err := cs.client.ListImages(context.TODO())
if err != nil {
return 0
}

return len(imgs)
}

func (cs *containerdStore) LayerStoreStatus() [][2]string {
return [][2]string{}
}

func (cs *containerdStore) GetContainerLayerSize(containerID string) (int64, int64) {
panic("not implemented")
}

func (cs *containerdStore) UpdateConfig(maxDownloads, maxUploads int) {
panic("not implemented")
}

func (cs *containerdStore) Children(id image.ID) []image.ID {
panic("not implemented")
}
11 changes: 8 additions & 3 deletions daemon/daemon.go
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/docker/docker/builder"
"github.com/docker/docker/container"
"github.com/docker/docker/daemon/config"
ctrd "github.com/docker/docker/daemon/containerd"
"github.com/docker/docker/daemon/events"
"github.com/docker/docker/daemon/exec"
_ "github.com/docker/docker/daemon/graphdriver/register" // register graph drivers
Expand Down Expand Up @@ -147,8 +148,8 @@ func (daemon *Daemon) Features() *map[string]bool {
return &daemon.configStore.Features
}

// usesSnapshotter returns true if feature flag to use containerd snapshotter is enabled
func (daemon *Daemon) usesSnapshotter() bool {
// UsesSnapshotter returns true if feature flag to use containerd snapshotter is enabled
func (daemon *Daemon) UsesSnapshotter() bool {
if daemon.configStore.Features != nil {
if b, ok := daemon.configStore.Features["containerd-snapshotter"]; ok {
return b
Expand Down Expand Up @@ -1091,7 +1092,11 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
// TODO: imageStore, distributionMetadataStore, and ReferenceStore are only
// used above to run migration. They could be initialized in ImageService
// if migration is called from daemon/images. layerStore might move as well.
d.imageService = images.NewImageService(imgSvcConfig)
if d.UsesSnapshotter() {
d.imageService = ctrd.NewService(d.containerdCli)
} else {
d.imageService = images.NewImageService(imgSvcConfig)
}
logrus.Debugf("Max Concurrent Downloads: %d", imgSvcConfig.MaxConcurrentDownloads)
logrus.Debugf("Max Concurrent Uploads: %d", imgSvcConfig.MaxConcurrentUploads)
logrus.Debugf("Max Download Attempts: %d", imgSvcConfig.MaxDownloadAttempts)
Expand Down
4 changes: 2 additions & 2 deletions daemon/oci_linux.go
Expand Up @@ -720,14 +720,14 @@ func sysctlExists(s string) bool {
// WithCommonOptions sets common docker options
func WithCommonOptions(daemon *Daemon, c *container.Container) coci.SpecOpts {
return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
if c.BaseFS == nil && !daemon.usesSnapshotter() {
if c.BaseFS == nil && !daemon.UsesSnapshotter() {
return errors.New("populateCommonSpec: BaseFS of container " + c.ID + " is unexpectedly nil")
}
linkedEnv, err := daemon.setupLinkedContainers(c)
if err != nil {
return err
}
if !daemon.usesSnapshotter() {
if !daemon.UsesSnapshotter() {
s.Root = &specs.Root{
Path: c.BaseFS.Path(),
Readonly: c.HostConfig.ReadonlyRootfs,
Expand Down

0 comments on commit 5d0eaf6

Please sign in to comment.