docker run -w 从 go 脚本运行时出现意外错误

标签 docker go

我正在编写一个非常简单的脚本,它只是通过 docker 为 go 应用程序格式化构建命令。它格式化命令如下:

docker run --rm -v c:/Users/me/go/src/goapp:/go/src/goapp -w /go/src/goapp -e GOOS=os -e GOARCH=arch image go build -v -o outputname

运行它时,我得到以下信息:

docker: Error response from daemon: the working directory ' /go/src/goapp' is invalid, it needs to be an absolute path

我试过像这样重新格式化它:

docker run --rm -v="c:/Users/me/go/src/goapp:/go/src/goapp" -w="/go/src/goapp" -e="GOOS=os" -e"GOARCH=arch" image go build -v -o outputname

得到同样的错误,只有“无效”的工作目录是"/go/src/goapp"

这是我的代码:

package main

import (
    "bytes"
    "flag"
    "fmt"
    "os"
    "os/exec"
    "runtime"
    "strings"
)

func constructCmd(volumeMap, workingDir, goos, goarch, output, image string) []string {
    finalCmd := append([]string{"run", "--rm"},
        fmt.Sprintf("-v='%s'", volumeMap),
        fmt.Sprintf("-w='%s'", workingDir),
        fmt.Sprintf("-e='%s'", goos),
        fmt.Sprintf("-e='%s'", goarch),
    )

    finalCmd = append(finalCmd, image, "go build -v")

    if output != "" {
        finalCmd = append(finalCmd, fmt.Sprintf("-o %s", output))
    }

    return finalCmd
}

func main() {
    // Parse flags
    osPtr := flag.String("os", "windows", "Target distribution")
    archPtr := flag.String("arch", "amd64", "Target distribution")
    outputPtr := flag.String("out", "", "Output file name")
    flag.Parse()

    fmt.Printf("Building for %s/%s:\n", *osPtr, *archPtr)

    goos := "GOOS=" + *osPtr
    goarch := "GOARCH=" + *archPtr

    pwd, _ := os.Getwd()
    if runtime.GOOS == "windows" {
        pwd = strings.Replace(pwd, "C", "c", 1)
        pwd = strings.Replace(pwd, "\\", "/", -1)
    }
    workingDir := pwd[strings.Index(pwd, "/go"):]
    volumeMap := fmt.Sprintf("%s:%s", pwd, workingDir)

    var image string
    if len(flag.Args()) == 0 {
        image = "golang"
    } else {
        image = flag.Args()[0]
    }

    execCmd := constructCmd(volumeMap, workingDir, goos, goarch, *outputPtr, image)

    cmd := exec.Command("docker", execCmd...)
    cmdOutput := &bytes.Buffer{}
    cmd.Stdout = cmdOutput
    cmd.Stderr = cmdOutput
    err := cmd.Run()
    if err != nil {
        os.Stderr.WriteString(err.Error())
    }
    fmt.Print(string(cmdOutput.Bytes()))
}

请注意,如果我直接运行此命令,则没有问题。没有错误。所以这不是 docker 问题,而是 go 问题。什么可能导致此错误?

最佳答案

删除引号。如 the exec package's documentation 中所述, Go 的标准 lib os/exec 包不会调用 shell 来执行 Cmd:

Unlike the "system" library call from C and other languages, the os/exec package intentionally does not invoke the system shell and does not expand any glob patterns or handle other expansions, pipelines, or redirections typically done by shells. The package behaves more like C's "exec" family of functions.

除非您在命令中调用 shell,否则不会调用 shell 来处理和删除这些引号。

例如,这个:

"-v='%s'"

应该是这样的:

"-v=%s"

评论更新:OP 还发现并修复了第二个问题:

"go build -v"

需要拆分成单独的参数:

"go", "build", "-v"

关于docker run -w 从 go 脚本运行时出现意外错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48724212/

相关文章:

node.js - 在 NodeJs 中使用 Docker-compose 热重载

python - 我在端口 8000 :80, 上的 apache+docker 上运行 django 应用程序需要用另一个端口运行另一个应用程序但不工作

docker - 何时将 `--attach` 与 `docker container run` 一起使用?

json - 将 json 解码为结构时如何不允许空字段

go - 开关盒不同类型与去

mysql - 从主机访问 Docker MySQL 服务器,无需容器的 IP 地址

docker - 在 Docker Swarm 内使用 “bind” 卷挂载和 docker-compose 文件

docker - 无法下载 docker golang 镜像 : No command specified

c - 为什么我不能从 Golang 中正确读取 C 常量?

python - 无法在 Go 中解码 post json python 请求