github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/engine/docker/image.go (about)

     1  package docker
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  
     8  	dockertypes "github.com/docker/docker/api/types"
     9  	dockerfilters "github.com/docker/docker/api/types/filters"
    10  	registrytypes "github.com/docker/docker/api/types/registry"
    11  	enginetypes "github.com/projecteru2/core/engine/types"
    12  )
    13  
    14  // ImageList list image
    15  func (e *Engine) ImageList(ctx context.Context, image string) ([]*enginetypes.Image, error) {
    16  	image = normalizeImage(image)
    17  	imgListFilter := dockerfilters.NewArgs()
    18  	imgListFilter.Add("reference", image) // 相同 repo 的image
    19  
    20  	images, err := e.client.ImageList(ctx, dockertypes.ImageListOptions{Filters: imgListFilter})
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  
    25  	r := []*enginetypes.Image{}
    26  	for _, image := range images {
    27  		i := &enginetypes.Image{
    28  			ID:   image.ID,
    29  			Tags: image.RepoTags,
    30  		}
    31  		r = append(r, i)
    32  	}
    33  	return r, nil
    34  }
    35  
    36  // ImageRemove remove a image
    37  func (e *Engine) ImageRemove(ctx context.Context, image string, force, prune bool) ([]string, error) {
    38  	opts := dockertypes.ImageRemoveOptions{
    39  		Force:         force,
    40  		PruneChildren: prune,
    41  	}
    42  
    43  	removed, err := e.client.ImageRemove(ctx, image, opts)
    44  	r := []string{}
    45  	if err != nil {
    46  		return r, err
    47  	}
    48  
    49  	for _, item := range removed {
    50  		if item.Untagged != "" {
    51  			r = append(r, item.Untagged)
    52  		}
    53  		if item.Deleted != "" {
    54  			r = append(r, item.Deleted)
    55  		}
    56  	}
    57  
    58  	return r, nil
    59  }
    60  
    61  // ImagesPrune prune images
    62  func (e *Engine) ImagesPrune(ctx context.Context) error {
    63  	_, err := e.client.ImagesPrune(ctx, dockerfilters.NewArgs())
    64  	return err
    65  }
    66  
    67  // ImagePull pull Image
    68  func (e *Engine) ImagePull(ctx context.Context, ref string, all bool) (io.ReadCloser, error) {
    69  	auth, err := makeEncodedAuthConfigFromRemote(e.config.Docker.AuthConfigs, ref)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	pullOptions := dockertypes.ImagePullOptions{All: all, RegistryAuth: auth}
    74  	return e.client.ImagePull(ctx, ref, pullOptions)
    75  }
    76  
    77  // ImagePush push image
    78  func (e *Engine) ImagePush(ctx context.Context, ref string) (io.ReadCloser, error) {
    79  	auth, err := makeEncodedAuthConfigFromRemote(e.config.Docker.AuthConfigs, ref)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	pushOptions := dockertypes.ImagePushOptions{RegistryAuth: auth}
    84  	return e.client.ImagePush(ctx, ref, pushOptions)
    85  }
    86  
    87  // ImageBuild build image
    88  func (e *Engine) ImageBuild(ctx context.Context, input io.Reader, refs []string, platform string) (io.ReadCloser, error) {
    89  	authConfigs := map[string]registrytypes.AuthConfig{}
    90  	for domain, conf := range e.config.Docker.AuthConfigs {
    91  		b64auth, err := encodeAuthToBase64(conf)
    92  		if err != nil {
    93  			return nil, err
    94  		}
    95  		if _, ok := authConfigs[domain]; !ok {
    96  			authConfigs[domain] = registrytypes.AuthConfig{
    97  				Username: conf.Username,
    98  				Password: conf.Password,
    99  				Auth:     b64auth,
   100  			}
   101  		}
   102  	}
   103  	buildOptions := dockertypes.ImageBuildOptions{
   104  		Tags:           refs,
   105  		SuppressOutput: false,
   106  		NoCache:        true,
   107  		Remove:         true,
   108  		ForceRemove:    true,
   109  		PullParent:     true,
   110  		Platform:       platform,
   111  		AuthConfigs:    authConfigs,
   112  	}
   113  	resp, err := e.client.ImageBuild(ctx, input, buildOptions)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	return resp.Body, nil
   118  }
   119  
   120  // ImageBuildFromExist commits image from running workload
   121  func (e *Engine) ImageBuildFromExist(ctx context.Context, ID string, refs []string, _ string) (imageID string, err error) {
   122  	opts := dockertypes.ContainerCommitOptions{
   123  		Reference: refs[0],
   124  		Author:    "eru-core",
   125  	}
   126  	resp, err := e.client.ContainerCommit(ctx, ID, opts)
   127  	if err != nil {
   128  		return "", err
   129  	}
   130  	for i := 1; i < len(refs); i++ {
   131  		if err := e.client.ImageTag(ctx, resp.ID, refs[i]); err != nil {
   132  			return "", err
   133  		}
   134  	}
   135  	return resp.ID, err
   136  }
   137  
   138  // ImageBuildCachePrune prune build cache
   139  func (e *Engine) ImageBuildCachePrune(ctx context.Context, all bool) (uint64, error) {
   140  	r, err := e.client.BuildCachePrune(ctx, dockertypes.BuildCachePruneOptions{All: all})
   141  	if err != nil {
   142  		return 0, err
   143  	}
   144  	return r.SpaceReclaimed, nil
   145  }
   146  
   147  // ImageLocalDigests return image digests
   148  func (e *Engine) ImageLocalDigests(ctx context.Context, image string) ([]string, error) {
   149  	inspect, _, err := e.client.ImageInspectWithRaw(ctx, image)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	return inspect.RepoDigests, nil
   154  }
   155  
   156  // ImageRemoteDigest return image digest at remote
   157  func (e *Engine) ImageRemoteDigest(ctx context.Context, image string) (string, error) {
   158  	auth, err := makeEncodedAuthConfigFromRemote(e.config.Docker.AuthConfigs, image)
   159  	if err != nil {
   160  		return "", err
   161  	}
   162  	inspect, err := e.client.DistributionInspect(ctx, image, auth)
   163  	if err != nil {
   164  		return "", err
   165  	}
   166  	remoteDigest := fmt.Sprintf("%s@%s", normalizeImage(image), inspect.Descriptor.Digest.String())
   167  	return remoteDigest, nil
   168  }