Выполнить команду powershell в работающем контейнере через Docker API - PullRequest
2 голосов
/ 17 апреля 2019

Я хочу выполнить команду powershell в контейнере Docker, работающем на хосте Windows.

Конкретная команда, которую я хочу выполнить: "powershell Get-PSDrive C | Select-Object Used,Free"

Я реализовал это с помощью Docker API для python, и это просто, как вызов:

cmd = "powershell Get-PSDrive C | Select-Object Used,Free"
output = container.exec_run(cmd)

Это работает как задумано, но мне нужно реализовать это в golang.

Но почему-то мне не понятно, как взаимодействовать с Docker API для golang. Я посмотрел на API и был смущен hijackedSession. Как мне настроить вызовы для ContainerExecCreate, ContainerExecAttach и ContainerExecStart?

Я ожидаю, что скрипт golang выдаст те же результаты, что и код python:

        Used         Free
        ----         ----
199181606912 307151622144

Который потом может быть проанализирован мной.

1 Ответ

1 голос
/ 21 апреля 2019

Структура HijackedResponse:

type HijackedResponse struct {
    Conn   net.Conn
    Reader *bufio.Reader
}


Вам необходимо скопировать ответ с resp.Reader, вот мой код:

package main

import (
    "bytes"
    "context"
    "fmt"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
    "github.com/docker/docker/pkg/stdcopy"
    "strings"
)

func readFromCommand() (string, error) {
    cli, err := client.NewEnvClient()
    if err != nil {
        return "", err
    }
    ctx := context.Background()
    config := types.ExecConfig{
        Cmd:          strings.Split("powershell Get-PSDrive C | Select-Object Used,Free", " "),
        AttachStdout: true,
        AttachStderr: true,
    }
    response, err := cli.ContainerExecCreate(ctx,
        // container id
        "cf59d65ab1", config)
    if err != nil {
        return "", err
    }
    execID := response.ID

    resp, err := cli.ContainerExecAttach(ctx, execID, config)
    if err != nil {
        return "", err
    }
    defer resp.Close()
    stdout := new(bytes.Buffer)
    stderr := new(bytes.Buffer)
    _, err = stdcopy.StdCopy(stdout, stderr, resp.Reader)
    if err != nil {
        return "", err
    }
    s := stdout.String()
    fmt.Println(s)
    i := stderr.String()
    fmt.Println(i)
    return s, nil

}

Не забудьте изменить идентификатор контейнера.

...