英文:
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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论