Johnsiilver
Johnsiilver

Reputation: 31

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

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!

Upvotes: 2

Views: 4928

Answers (1)

Ricardo Branco
Ricardo Branco

Reputation: 6079

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)
        }
}

Upvotes: 3

Related Questions