我正在尝试使用Docker API和Docker Go库(https://github.com/docker/engine-api/)构建Docker镜像。代码示例:
webpack
错误始终相同:
来自守护程序的错误响应:找不到指定的Dockerfile:dockerSrc / docker-debug-container / Dockerfile
或
来自守护程序的错误响应:找不到指定的Dockerfile:Dockerfile
我检查过的事情:
package main
import (
"fmt"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
func main() {
defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"}
cli, err := client.NewClient("unix:///var/run/docker.sock", "v1.22", nil, defaultHeaders)
if err != nil {
panic(err)
}
fmt.Print(cli.ClientVersion())
opt := types.ImageBuildOptions{
CPUSetCPUs: "2",
CPUSetMems: "12",
CPUShares: 20,
CPUQuota: 10,
CPUPeriod: 30,
Memory: 256,
MemorySwap: 512,
ShmSize: 10,
CgroupParent: "cgroup_parent",
Dockerfile: "dockerSrc/docker-debug-container/Dockerfile",
}
_, err = cli.ImageBuild(context.Background(), nil, opt)
if err == nil || err.Error() != "Error response from daemon: Server error" {
fmt.Printf("expected a Server Error, got %v", err)
}
}
Dockerfile
正常工作我的另一个选择是使用docker build <path>
,它看起来很有效,但仅适用于完全自包含的dockerfiles,而不是具有“本地文件存在”的那些。
更新
尝试传递RemoteContext
作为缓冲区,但得到的结果与以下内容相同:
tar
答案 0 :(得分:9)
@Mangirdas:盯着屏幕足够长的帮助 - 至少在我的情况下。一段时间以来,我一直困扰着同样的问题。 你是正确的使用tar文件(你的第二个例子)。如果你在这里查看API文档https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/build-image-from-a-dockerfile,你会发现它需要tar。 真正帮助我的是在我的案例中查看客户端的其他实现,perl和ruby。当被要求从目录构建映像时,它们都会动态创建tar。 无论如何,你只需要将dockerBuildContext放在其他地方(参见cli.ImageBuild())
dockerBuildContext, err := os.Open("/Path/to/your/docker/tarfile.tar")
defer dockerBuildContext.Close()
buildOptions := types.ImageBuildOptions{
Dockerfile: "Dockerfile", // optional, is the default
}
buildResponse, err := cli.ImageBuild(context.Background(), dockerBuildContext, buildOptions)
if err != nil {
log.Fatal(err)
}
defer buildResponse.Body.Close()
我还没有正确命名图像,但至少我可以创建它们...... 希望这可以帮助。 干杯
答案 1 :(得分:5)
以下适用于我;
package main
import (
"archive/tar"
"bytes"
"context"
"io"
"io/ioutil"
"log"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
log.Fatal(err, " :unable to init client")
}
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
defer tw.Close()
dockerFile := "myDockerfile"
dockerFileReader, err := os.Open("/path/to/dockerfile")
if err != nil {
log.Fatal(err, " :unable to open Dockerfile")
}
readDockerFile, err := ioutil.ReadAll(dockerFileReader)
if err != nil {
log.Fatal(err, " :unable to read dockerfile")
}
tarHeader := &tar.Header{
Name: dockerFile,
Size: int64(len(readDockerFile)),
}
err = tw.WriteHeader(tarHeader)
if err != nil {
log.Fatal(err, " :unable to write tar header")
}
_, err = tw.Write(readDockerFile)
if err != nil {
log.Fatal(err, " :unable to write tar body")
}
dockerFileTarReader := bytes.NewReader(buf.Bytes())
imageBuildResponse, err := cli.ImageBuild(
ctx,
dockerFileTarReader,
types.ImageBuildOptions{
Context: dockerFileTarReader,
Dockerfile: dockerFile,
Remove: true})
if err != nil {
log.Fatal(err, " :unable to build docker image")
}
defer imageBuildResponse.Body.Close()
_, err = io.Copy(os.Stdout, imageBuildResponse.Body)
if err != nil {
log.Fatal(err, " :unable to read image build response")
}
}
答案 2 :(得分:4)
我同意Marcus Havranek的回答,这种方法对我有用。只想添加如何为图像添加名称,因为这似乎是一个悬而未决的问题:
buildOptions := types.ImageBuildOptions{
Tags: []string{"imagename"},
}
希望这有帮助!
答案 3 :(得分:1)
我遇到同样的问题。最终发现即使使用Dockerfile,tar文件也应该是docker build上下文。
这是我的代码,
package main
import (
"log"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
func main() {
dockerBuildContext, err := os.Open("/Users/elsvent/workspace/Go/src/test/test.tar")
defer dockerBuildContext.Close()
buildOptions := types.ImageBuildOptions{
SuppressOutput: true,
PullParent: true,
Tags: []string{"xxx"},
Dockerfile: "test/Dockerfile",
}
defaultHeaders := map[string]string{"Content-Type": "application/tar"}
cli, _ := client.NewClient("unix:///var/run/docker.sock", "v1.24", nil, defaultHeaders)
buildResp, err := cli.ImageBuild(context.Background(), dockerBuildContext, buildOptions)
if err != nil {
log.Fatal(err)
}
defer buildResp.Body.Close()
}
答案 4 :(得分:1)
Docker软件包具有用于从文件路径创建TAR的功能。它是CLI使用的功能。它不在客户端软件包中,因此需要单独安装:
import (
"github.com/mitchellh/go-homedir"
"github.com/docker/docker/pkg/archive"
)
func GetContext(filePath string) io.Reader {
// Use homedir.Expand to resolve paths like '~/repos/myrepo'
filePath, _ := homedir.Expand(filePath)
ctx, _ := archive.TarWithOptions(filePath, &archive.TarOptions{})
return ctx
}
cli.ImageBuild(context.Background(), GetContext("~/repos/myrepo"), types.ImageBuildOptions{...})
答案 5 :(得分:0)
结合一些答案,并添加如何使用DisplayJSONMessagesToStream正确解析返回的JSON。
package main
import (
"os"
"log"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/term"
"golang.org/x/net/context"
)
// Build a dockerfile if it exists
func Build(dockerFilePath, buildContextPath string, tags []string) {
ctx := context.Background()
cli := getCLI()
buildOpts := types.ImageBuildOptions{
Dockerfile: dockerFilePath,
Tags: tags,
}
buildCtx, _ := archive.TarWithOptions(buildContextPath, &archive.TarOptions{})
resp, err := cli.ImageBuild(ctx, buildCtx, buildOpts)
if err != nil {
log.Fatalf("build error - %s", err)
}
defer resp.Body.Close()
termFd, isTerm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stderr, termFd, isTerm, nil)
}
我已经离开了一些方便的功能,例如getCLI
,但我确定您有自己的等效功能。
答案 6 :(得分:0)
<IfModule>