这让我失望。我不确定我做错了什么。文档较少,搜索没有产生良好的结果。我很高兴看到这种奇怪行为背后的原因是什么。
我在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请求。但不确定为什么它不会构建任何东西。
答案 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"