golang使用docker的sdk进行构建镜像,拉取镜像,上传镜像等操作
文章目录一、golang操作docker操作镜像二 、删除镜像为标签 none:none 的操作一、golang操作docker操作镜像最近,由于业务上面的需要,需要构建镜像,在查了一些资料之后,将构建镜像、push镜像、pull镜像总结了一下,尤其在构建镜像的时候我们需要注意的点比较多,下面直接放代码// 1.Docker docker clienttype Docker struct {*cl
·
一、golang操作docker操作镜像
最近,由于业务上面的需要,需要构建镜像,在查了一些资料之后,将构建镜像、push镜像、pull镜像总结了一下,尤其在构建镜像的时候我们需要注意的点比较多,下面直接放代码
// 1.Docker docker client
type Docker struct {
*client.Client
}
// 2.init docker client
func NewDockerClient() *Docker {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil
}
return &Docker{
cli,
}
}
// Images get images from
func (d *Docker) Images(opt types.ImageListOptions) ([]types.ImageSummary, error) {
return d.ImageList(context.TODO(), opt)
}
//PushImage--> pull image to harbor仓库
func (d *Docker) PushImage(image string) error {
authConfig := types.AuthConfig{
Username: setting.HarborSetting.User, //harbor用户名 (这一块我是读的配置文件,需要的可以进行修改)
Password: setting.HarborSetting.Pwd, //harbor 密码
}
encodedJSON, err := json.Marshal(authConfig)
if err != nil {
return err
}
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
out, err := d.ImagePush(context.TODO(), image, types.ImagePushOptions{RegistryAuth: authStr})
if err != nil {
return err
}
body, err := ioutil.ReadAll(out)
if err != nil {
return err
}
fmt.Sprintf("Push docker image output: %v", string(body))
if strings.Contains(string(body), "error") {
return fmt.Errorf("push image to docker error")
}
return nil
}
//PullImage pull image
func (d *Docker) PullImage(name string) error {
resp, err := d.ImagePull(context.TODO(), name, types.ImagePullOptions{})
if err != nil {
return err
}
_, err = io.Copy(ioutil.Discard, resp)
if err != nil {
return err
}
return nil
}
// RemoveImage remove image 这里需要注意的一点就是移除了镜像之后,
//会出现<none>:<none>的标签,这个是因为下载的镜像是分层的,所以删除会导致
func (d *Docker) RemoveImage(name string) error {
_, err := d.ImageRemove(context.TODO(), name, types.ImageRemoveOptions{})
return err
}
//RemoveDanglingImages remove dangling images <none>
func (d *Docker) RemoveDanglingImages() error {
opt := types.ImageListOptions{
Filters: filters.NewArgs(filters.Arg("dangling", "true")),
}
images, err := d.Images(opt)
if err != nil {
return err
}
errIDs := []string{}
for _, image := range images {
fmt.Printf("image.ID: %v\n", image.ID)
if err := d.RemoveImage(image.ID); err != nil {
errIDs = append(errIDs, image.ID[7:19])
}
}
if len(errIDs) > 1 {
return fmt.Errorf("can not remove ids\n%s", errIDs)
}
return nil
}
// SaveImage save image to tar file
func (d *Docker) SaveImage(ids []string, path string) error {
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
return err
}
defer file.Close()
out, err := d.ImageSave(context.TODO(), ids)
if err != nil {
return err
}
if _, err = io.Copy(file, out); err != nil {
return err
}
return nil
}
// LoadImage load image from tar file
func (d *Docker) LoadImage(path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = d.ImageLoad(context.TODO(), file, true)
return err
}
// ImportImage import image
func (d *Docker) ImportImage(name, tag, path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
source := types.ImageImportSource{
Source: file,
SourceName: "-",
}
opt := types.ImageImportOptions{
Tag: tag,
}
_, err = d.ImageImport(context.TODO(), source, name, opt)
return err
}
// SearchImage search images
func (d *Docker) SearchImage(name string) ([]registry.SearchResult, error) {
return d.ImageSearch(context.TODO(), name, types.ImageSearchOptions{Limit: 100})
}
//Buildimage build image image 需要构建的镜像名称
func (d *Docker) Buildimage(warName, image string) error {
// 1.需要构建的war包上传到docker/web/目录下
err := file.CopyFile(fmt.Sprintf("/tmp/docker/%s", warName), fmt.Sprintf("docker/web/%s", warName))
if err != nil {
return err
}
var tags []string
tags = append(tags, image)
//打一个docker.tar包
tarit("docker/", ".") //src:要打包文件的源地址 target:要打包文件的目标地址 (使用相对路径-->相对于main.go)
//打开刚刚打的tar包
dockerBuildContext, _ := os.Open("docker.tar") //打开打包的文件,
defer dockerBuildContext.Close()
options := types.ImageBuildOptions{
Dockerfile: "docker/Dockerfile", //不能是绝对路径 是相对于build context来说的,
SuppressOutput: false,
Remove: true,
ForceRemove: true,
PullParent: true,
Tags: tags, //[]string{"192.168.0.1/harbor/cdisample:v1"}
}
buildResponse, err := d.ImageBuild(context.Background(), dockerBuildContext, options)
fmt.Printf("err build: %v\n", err)
if err != nil {
fmt.Printf("%s", err.Error())
return err
}
fmt.Printf("********* %s **********", buildResponse.OSType)
response, err := ioutil.ReadAll(buildResponse.Body)
if err != nil {
fmt.Printf("%s", err.Error())
return err
}
fmt.Println(string(response))
return nil
}
/*
source:打包的的路径
target:放置打包文件的位置
*/
func tarit(source string, target string) error {
filename := filepath.Base(source)
fmt.Println(filename)
target = filepath.Join(target, fmt.Sprintf("%s.tar", filename))
//target := fmt.Sprintf("%s.tar", filename)
fmt.Println(target)
tarfile, err := os.Create(target)
if err != nil {
return err
}
fmt.Println(tarfile)
defer tarfile.Close()
tarball := tar.NewWriter(tarfile)
// 这里不要忘记关闭,如果不能成功关闭会造成 tar 包不完整
// 所以这里在关闭的同时进行判断,可以清楚的知道是否成功关闭
defer func() {
if err := tarball.Close(); err != nil {
utils.ErrPrintln(err)
}
}()
info, err := os.Stat(source)
if err != nil {
return nil
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Base(source)
}
return filepath.Walk(source,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
}
if err := tarball.WriteHeader(header); err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(tarball, file)
return err
})
}
- 关于构建镜像这一块需要注意的点
- 构建镜像需要将我们需要的文件(包括Dockerfile)打成一个tar包,这里建议名字就使用这个默认的名称就行。
types.ImageBuildOptions
中Dockerfile需要使用想对路径,而且是相对于build context 的路径来说的。使用绝对路径会报错
在我业务中主要是体现在构建镜像的过程中将临时文件中的war包复制我的docker/web目录下和Dockerfile文件进行一个tar打包。如下所示
Dockerfile中主要就是将war包添加到我们需要的镜像中,然后构建。
上面说到了如果是绝对路径会报错的问题,我接下来进行一个模拟。我在当前目录有一个Dockerfile文件和一个wa包进行一个构建。
Dockerfile文件
开始构建,发现已经报错,看他报错的提示,说明构建的必须是一个目录。
,这里报错的原因是ADD 文件的时候也不能使用绝对路径,他添加的文件必须也是相对路径,而且相对于docker build
的路径才能够构建成功
下面换成相对路径在重新构建一下,这样就可以构建镜像了。
使用docker images
查看镜像,发现确实这个镜像已经存在。
二 、删除镜像为标签 none:none 的操作
这两种方式都可以进行删除
docker images|grep none|awk '{print $3 }'|xargs docker rmi
docker rmi -f `docker images | grep none | awk '{print $3}'`
当然可以使用命令docker images prune
进行删除
更多推荐
已为社区贡献3条内容
所有评论(0)