mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 16:10:59 +08:00
119 lines
2.9 KiB
Go
119 lines
2.9 KiB
Go
package data
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/moby/moby/api/types/registry"
|
|
"github.com/moby/moby/client"
|
|
|
|
"github.com/acepanel/panel/internal/biz"
|
|
"github.com/acepanel/panel/internal/http/request"
|
|
"github.com/acepanel/panel/pkg/tools"
|
|
"github.com/acepanel/panel/pkg/types"
|
|
)
|
|
|
|
type containerImageRepo struct{}
|
|
|
|
func NewContainerImageRepo() biz.ContainerImageRepo {
|
|
return &containerImageRepo{}
|
|
}
|
|
|
|
// List 列出镜像
|
|
func (r *containerImageRepo) List() ([]types.ContainerImage, error) {
|
|
apiClient, err := getDockerClient("/var/run/docker.sock")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
|
|
|
|
resp, err := apiClient.ImageList(context.Background(), client.ImageListOptions{
|
|
All: true,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var images []types.ContainerImage
|
|
for _, item := range resp.Items {
|
|
images = append(images, types.ContainerImage{
|
|
ID: item.ID,
|
|
Containers: item.Containers,
|
|
RepoTags: item.RepoTags,
|
|
RepoDigests: item.RepoDigests,
|
|
Size: tools.FormatBytes(float64(item.Size)),
|
|
Labels: types.MapToKV(item.Labels),
|
|
CreatedAt: time.Unix(item.Created, 0),
|
|
})
|
|
}
|
|
|
|
slices.SortFunc(images, func(a types.ContainerImage, b types.ContainerImage) int {
|
|
return strings.Compare(a.ID, b.ID)
|
|
})
|
|
|
|
return images, nil
|
|
}
|
|
|
|
// Pull 拉取镜像
|
|
func (r *containerImageRepo) Pull(req *request.ContainerImagePull) error {
|
|
apiClient, err := getDockerClient("/var/run/docker.sock")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
|
|
|
|
options := client.ImagePullOptions{}
|
|
if req.Auth {
|
|
authConfig := registry.AuthConfig{
|
|
Username: req.Username,
|
|
Password: req.Password,
|
|
}
|
|
encodedJSON, err := json.Marshal(authConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
|
|
options.RegistryAuth = authStr
|
|
}
|
|
|
|
out, err := apiClient.ImagePull(context.Background(), req.Name, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func(out client.ImagePullResponse) { _ = out.Close() }(out)
|
|
|
|
// TODO 实现流式显示拉取进度
|
|
return out.Wait(context.Background())
|
|
}
|
|
|
|
// Remove 删除镜像
|
|
func (r *containerImageRepo) Remove(id string) error {
|
|
apiClient, err := getDockerClient("/var/run/docker.sock")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
|
|
|
|
_, err = apiClient.ImageRemove(context.Background(), id, client.ImageRemoveOptions{
|
|
Force: true,
|
|
PruneChildren: true,
|
|
})
|
|
return err
|
|
}
|
|
|
|
// Prune 清理未使用的镜像
|
|
func (r *containerImageRepo) Prune() error {
|
|
apiClient, err := getDockerClient("/var/run/docker.sock")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
|
|
|
|
_, err = apiClient.ImagePrune(context.Background(), client.ImagePruneOptions{})
|
|
return err
|
|
}
|