13

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

エラーは常に同じです:

デーモンからのエラー応答: 指定された Dockerfile が見つかりません: dockerSrc/docker-debug-container/Dockerfile

また

デーモンからのエラー応答: 指定された Dockerfile が見つかりません: Dockerfile

私がチェックしたこと:

  1. フォルダはビルド パスに存在します
  2. 相対パスと絶対パスの両方を試しました
  3. パスにソフトリンクがありません
  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)
4

7 に答える 7

13

以下は私にとってはうまくいきます。

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")
    }
}
于 2017-10-02T01:50:00.660 に答える
11

@Mangirdas:少なくとも私の場合は、画面を十分に長く見つめることが役に立ちます。私はしばらくの間同じ問題で立ち往生しています。tar ファイルを使用するのは正しかったです (2 番目の例)。https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/build-image-from-a-dockerfileの API ドキュメントを見ると、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()

画像に適切な名前を付けることはまだできていませんが、少なくとも作成することはできます...これが役に立てば幸いです。乾杯

于 2016-08-30T13:36:48.683 に答える
7

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{...})
于 2018-10-02T23:43:59.727 に答える