2016-08-06 3 views
1

Попытка построить Docker изображение с помощью докер API и Docker Go библиотеки: https://github.com/docker/engine-api/Построить Docker Image От Go кодекса

Пример кода:

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) 
    } 
  1. Папка существует в пути сборки
  2. Пробовал относительная и абсолютный путь
  3. Никаких программных ссылок на пути
  4. Пробовал то же самое Папка для двоичной и Dockerfile
  5. докер строительные работы
  6. и кучу других вещей

ошибки всегда одинаков:

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

или

Error response from daemon: Cannot locate specified Dockerfile: Dockerfile 

Другой вариант заключается в использовании RemoteContext, который выглядит как работает, но это прекрасно только для полностью автономных док-файлов ... и не те, с «локальным присутствием файла»

Update: Пробовал прохождение смолы в качестве буфера, но тот же самый материал:

 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) 

ответ

5

@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() 

Я не там с именования изображений пока должным образом, но, по крайней мере, я могу создать их ... Надеюсь это поможет. Cheers

+0

Я закончил делать это:/Так выглядит как-то способ сделать это сейчас. – Mangirdas

+0

Вам не нужно называть close на dockerBuildContext; 'defer dockerBuildContext.Close()' Это потому, что cli.ImageBuild называет go net/http client; https://github.com/moby/moby/blob/master/client/image_build.go#L34 И клиент go всегда закрывает тело запроса по умолчанию; https://github.com/golang/go/blob/c8aec4095e089ff6ac50d18e97c3f46561f14f48/src/net/http/client.go#L472 – Komu

1

Я согласен с ответом Маркуса Хавранека, этот метод работал на меня. Просто хочу добавить, как добавить имя к изображению, так как это казалось открытым вопросом:

buildOptions := types.ImageBuildOptions{ 
    Tags: []string{"imagename"}, 
} 

Надеюсь, это поможет!

1

Следующие работы для меня;

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