一、golang操作docker操作镜像
最近,由于业务上面的需要,需要构建镜像,在查了一些资料之后,将构建镜像、push镜像、pull镜像总结了一下,尤其在构建镜像的时候我们需要注意的点比较多,下面直接放代码
type Docker struct {
*client.Client
}
func NewDockerClient() *Docker {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil
}
return &Docker{
cli,
}
}
func (d *Docker) Images(opt types.ImageListOptions) ([]types.ImageSummary, error) {
return d.ImageList(context.TODO(), opt)
}
func (d *Docker) PushImage(image string) error {
authConfig := types.AuthConfig{
Username: setting.HarborSetting.User,
Password: setting.HarborSetting.Pwd,
}
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
}
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
}
func (d *Docker) RemoveImage(name string) error {
_, err := d.ImageRemove(context.TODO(), name, types.ImageRemoveOptions{})
return err
}
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
}
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
}
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
}
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
}
func (d *Docker) SearchImage(name string) ([]registry.SearchResult, error) {
return d.ImageSearch(context.TODO(), name, types.ImageSearchOptions{Limit: 100})
}
func (d *Docker) Buildimage(warName, image string) error {
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)
tarit("docker/", ".")
dockerBuildContext, _ := os.Open("docker.tar")
defer dockerBuildContext.Close()
options := types.ImageBuildOptions{
Dockerfile: "docker/Dockerfile",
SuppressOutput: false,
Remove: true,
ForceRemove: true,
PullParent: true,
Tags: tags,
}
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
}
func tarit(source string, target string) error {
filename := filepath.Base(source)
fmt.Println(filename)
target = filepath.Join(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)
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 进行删除
|