Docker客户端构建错误

时间:2016-10-06 10:05:13

标签: go docker

这让我失望。我不确定我做错了什么。文档较少,搜索没有产生良好的结果。我很高兴看到这种奇怪行为背后的原因是什么。

我在MAC(10.11.6),我正在为MAC(beta)运行docker

这是我试图运行的代码

package main

import (
    "fmt"

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

func main() {
    defaultHeaders := map[string]string{"User-Agent": "ego-v-0.0.1"}
    cli, _ := client.NewClient("unix:///var/run/docker.sock", "v1.24", nil, defaultHeaders)
    options := types.ImageBuildOptions{
        Dockerfile:     "/path/to/my/Dockerfile",
        SuppressOutput: false,
        Remove:         true,
        ForceRemove:    true,
        PullParent:     true}
    buildResponse, err := cli.ImageBuild(context.Background(), nil, options)
    if err != nil {
        fmt.Printf("%s", err.Error())
    }
    fmt.Printf("%s", buildResponse.OSType)
}

这给了我这个错误 -

Error response from daemon: {"message":"Cannot locate specified Dockerfile: /path/to/my/Dockerfile"}

然而,当我运行此命令时(来自我的Go代码所在的同一目录)

docker build /path/to/my

它绝对正常。

我做错了什么?我现在想把头撞在墙上。请帮忙。

------------ EDIT / ADD ------------ 我最终这样做了 -

package main

import (
    "archive/tar"
    "fmt"
    "io"
    "os"
    "path/filepath"
    "strings"

    "golang.org/x/net/context"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func tarit(source, target string) error {
    filename := filepath.Base(source)
    target = filepath.Join(target, fmt.Sprintf("%s.tar", filename))
    fmt.Println(target)
    tarfile, err := os.Create(target)
    if err != nil {
        return err
    }
    defer tarfile.Close()

    tarball := tar.NewWriter(tarfile)
    defer tarball.Close()

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

func main() {
    tarit("/dir/with/files/and/dockerfile", "repo")
    dockerBuildContext, err := os.Open("./repo.tar")
    defer dockerBuildContext.Close()
    defaultHeaders := map[string]string{"User-Agent": "ego-v-0.0.1"}
    cli, _ := client.NewClient("unix:///var/run/docker.sock", "v1.24", nil, defaultHeaders)
    options := types.ImageBuildOptions{
        Dockerfile:     "repo/Dockerfile",
        SuppressOutput: false,
        Remove:         true,
        ForceRemove:    true,
        PullParent:     true}
    buildResponse, err := cli.ImageBuild(context.Background(), dockerBuildContext, options)
    if err != nil {
        fmt.Printf("%s", err.Error())
    }
    fmt.Printf("********* %s **********", buildResponse.OSType)
}

现在它没有抱怨什么,我可以看到tar正在制作正确并且最后一个println正在打印

********* linux **********

这是来自服务器的回复。但它没有构建任何东西。我知道答案几乎是立即的,因为它只是一个POST请求。但不确定为什么它不会构建任何东西。

2 个答案:

答案 0 :(得分:0)

Dockerfile必须是获取TARd并发送到引擎的构建上下文的一部分。您不应该使用Dockerfile的绝对路径must be relative to the context,因此您只需传递名称。

我不认为您演示的CLI命令是正确的 - 除非Dockerfile实际上是您的案例中的目录名称:

> ls /tmp/path/to/context 
Dockerfile
> docker build /tmp/path/to/context/Dockerfile
unable to prepare context: context must be a directory: /tmp/path/to/context/Dockerfile

当你只发送路径(包含Dockerfile文件)时,它起作用:

> docker build /tmp/path/to/context
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine
 ---> ee4603260daa
Successfully built ee4603260daa

答案 1 :(得分:0)

此问题的工作代码。对于那些可能会像我一样被卡住的人 -

package main

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

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

func main() {
    tar := new(archivex.TarFile)
    tar.Create("/path/to/tar/archieve")
    tar.AddAll("/path/to/base/folder", false)
    tar.Close()
    dockerBuildContext, err := os.Open("/path/to/tar/archieve.tar")
    defer dockerBuildContext.Close()
    defaultHeaders := map[string]string{"Content-Type": "application/tar"}
    cli, _ := client.NewClient("unix:///var/run/docker.sock", "v1.24", nil, defaultHeaders)
    options := types.ImageBuildOptions{
        SuppressOutput: true,
        Remove:         true,
        ForceRemove:    true,
        PullParent:     true,
        Tags:           []string{"xxx"}}
    buildResponse, err := cli.ImageBuild(context.Background(), dockerBuildContext, options)
    defer buildResponse.Body.Close()
    if err != nil {
        fmt.Printf("%s", err.Error())
    }
    //time.Sleep(5000 * time.Millisecond)
    fmt.Printf("********* %s **********", buildResponse.OSType)
    response, err := ioutil.ReadAll(buildResponse.Body)
    if err != nil {
        fmt.Printf("%s", err.Error())
    }
    fmt.Println(string(response))
}

请注意,此代码中未执行大量错误检查。这只是一个有效的代码,我正在成功使用docker client lib。

让我知道你的想法。

感谢 -

  

" github.com/jhoonb/archivex"