go - 从 Go 代码构建 Docker 镜像

标签 go docker dockerfile docker-api

我正在尝试使用 Docker API 和 Docker Go 库 (https://github.com/docker/engine-api/) 构建 Docker 镜像。代码示例:

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

错误总是一样的:

Error response from daemon: Cannot locate specified Dockerfile: dockerSrc/docker-debug-container/Dockerfile

Error response from daemon: Cannot locate specified Dockerfile: Dockerfile

我检查过的内容:

  1. 该文件夹存在于构建路径中
  2. 我尝试了相对路径和绝对路径
  3. 路径中没有软链接(soft link)
  4. 我为二进制文件和 Dockerfile 尝试了相同的文件夹
  5. docker build <path>有效
  6. 还有很多其他的东西

我的另一个选择是使用 RemoteContext看起来它有效,但仅适用于完全自包含的 dockerfile,而不是具有“本地文件存在”的那些。


更新: 尝试通过 tar作为缓冲区,但得到了相同的结果:

  dockerBuildContext, err := os.Open("<path to>/docker-debug-    container/docker-debug-container.tar")
  defer dockerBuildContext.Close()

    opt := types.ImageBuildOptions{
        Context:      dockerBuildContext,
        CPUSetCPUs:   "2",
        CPUSetMems:   "12",
        CPUShares:    20,
        CPUQuota:     10,
        CPUPeriod:    30,
        Memory:       256,
        MemorySwap:   512,
        ShmSize:      10,
        CgroupParent: "cgroup_parent",
        //  Dockerfile:   "Dockerfile",
    }

    _, err = cli.ImageBuild(context.Background(), nil, opt)

最佳答案

以下对我有用;

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

关于go - 从 Go 代码构建 Docker 镜像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38804313/

相关文章:

dictionary - 修改后的 slice 元素无法通过 map 访问。我究竟做错了什么?

docker - Kubernetes Nginx Web服务器配置映射停止Nginx工作

ruby-on-rails - Docker和Rails环境

docker - 如果我们多次将具有相同标签的同一个镜像推送到同一个 docker 存储库,为什么 Docker 镜像的 SHA256 摘要会发生变化

docker - kata 容器可以用作沙箱来运行不受信任的代码吗?

docker - 为什么 Docker 构建在 "Sending context to daemon"步骤中需要很长时间?

io - 从 Writer 获取字符串的最佳方法

garbage-collection - Go 使用什么样的垃圾收集器?

go - 仅使用stdlib在Golang中进行路由

docker - 如何在Docker容器上使用Dhcp中的IP地址