从Golang中的Docker镜像中拉取文件到本地文件系统

huangapple go评论110阅读模式
英文:

Pull a file from a docker image in Golang to local file system

问题

我正在尝试弄清楚如何使用Go客户端(http://godoc.org/github.com/moby/moby/client)从特定版本(标签)的Docker镜像中提取文件。

我想要下载镜像,然后将镜像中的文件复制到本地文件系统。我看到了很多处理镜像的命令,但没有看到如何访问其内容。我确实看到了访问容器内容的方法。

我怀疑我需要下载镜像,使用该镜像创建一个容器,最后将容器中的内容复制出来。不过,如果能避免创建容器,那就更好了。

有人知道如何准确地做到这一点吗?如果有代码片段就更好了。

谢谢!

英文:

I’m trying to figure out how I can use the Go client (http://godoc.org/github.com/moby/moby/client) to pull a file from a docker image at a specific version (tag)

I want to download the image and then copy a file from the image onto the local file system. I see a lot of commands for dealing with an image, but not how to access its contents. I do see ways to access a container’s contents.

I’m suspecting I would need to download the image, create a container with the image and finally copy the contents out of the container. Though if I could avoid creating a container, that would be preferred.

Does anyone know exactly how to do this? Code snippet would be appreciated.

Thanks!

答案1

得分: 3

你必须先启动容器,然后复制文件,最后删除容器... 这并不是一个昂贵的操作,因为容器无论如何都不会启动。

以下是一个可以工作的示例,它将文件从指定的镜像复制到标准输出。API 很容易理解:

package main

import (
        "archive/tar"
        "fmt"
        "io"
        "io/ioutil"
        "os"

        "github.com/docker/docker/api/types"
        "github.com/docker/docker/api/types/container"
        "github.com/docker/docker/client"
        "golang.org/x/net/context"
)

func main() {
        if len(os.Args) != 3 {
                fmt.Fprintf(os.Stderr, "Usage: %s IMAGE FILE\n", os.Args[0])
                os.Exit(1)
        }
        imageName := os.Args[1]
        filePath := os.Args[2]

        ctx := context.Background()
        cli, err := client.NewEnvClient()
        if err != nil {
                panic(err)
        }

        out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
        if err != nil {
                panic(err)
        }
        defer out.Close()
        if _, err := ioutil.ReadAll(out); err != nil {
                panic(err)
        }

        info, err := cli.ContainerCreate(ctx, &container.Config{
                Image: imageName,
        }, nil, nil, "")
        if err != nil {
                panic(err)
        }

        tarStream, _, err := cli.CopyFromContainer(ctx, info.ID, filePath)
        if err != nil {
                panic(err)
        }
        tr := tar.NewReader(tarStream)
        if _, err := tr.Next(); err != nil {
                panic(err)
        }

        io.Copy(os.Stdout, tr)

        if err := cli.ContainerRemove(ctx, info.ID, types.ContainerRemoveOptions{}); err != nil {
                panic(err)
        }
}

你可以参考以上代码示例来实现你的需求。

英文:

You must start the container, copy the file and then remove the container... It's not really an expensive operation since the container isn't started anyway.

Here's a working example that copies a file from the specified image to standard output. The API is straightforward to follow:

https://gist.github.com/ricardobranco777/a3be772935dfb1a183e0831496925585

package main
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s IMAGE FILE\n", os.Args[0])
os.Exit(1)
}
imageName := os.Args[1]
filePath := os.Args[2]
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
if err != nil {
panic(err)
}
defer out.Close()
if _, err := ioutil.ReadAll(out); err != nil {
panic(err)
}
info, err := cli.ContainerCreate(ctx, &container.Config{
Image: imageName,
}, nil, nil, "")
if err != nil {
panic(err)
}
tarStream, _, err := cli.CopyFromContainer(ctx, info.ID, filePath)
if err != nil {
panic(err)
}
tr := tar.NewReader(tarStream)
if _, err := tr.Next(); err != nil {
panic(err)
}
io.Copy(os.Stdout, tr)
if err := cli.ContainerRemove(ctx, info.ID, types.ContainerRemoveOptions{}); err != nil {
panic(err)
}
}

huangapple
  • 本文由 发表于 2017年8月22日 05:10:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/45805563.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定