无法使用Go客户端从Docker到达stdout

前端之家收集整理的这篇文章主要介绍了无法使用Go客户端从Docker到达stdout前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我有一个小项目,我的服务器将http发送的C文件复制到Docker容器中,在那里编译和运行它们.
但是,我无法获取任何数据发送到容器中的stdout.

我已确定将文件发送到Docker容器中,还有更多 – 编译的任何问题都显示错误流中.但是,在C程序中通过stderr发送数据也没有显示任何结果,直到我使用Dockerfile,使用’>& 2 echo“”’以某种方式将数据推送到流中并且我能够读取它.

现在,如上所述,我只能阅读stderr,完全归功于一种解决方法.知道为什么我不能使用标准方法吗?

去服务器

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "io"
  6. "os"
  7. "os/exec"
  8. "log"
  9. "encoding/json"
  10. "github.com/docker/docker/client"
  11. dockertypes "github.com/docker/docker/api/types"
  12. "github.com/docker/docker/api/types/container"
  13. "golang.org/x/net/context"
  14. "time"
  15. "bytes"
  16. )
  17. type Result struct {
  18. CompilationCode int
  19. RunCode int
  20. TestsPositive int
  21. TestsTotal int
  22. }
  23. func upload(w http.ResponseWriter,r *http.Request) {
  24. log.Println("method:",r.Method)
  25. if r.Method == "POST" {
  26. log.Println("Processing new SUBMISSION.")
  27. // https://github.com/astaxie/build-web-application-with-golang/blob/master/de/04.5.md
  28. r.ParseMultipartForm(32 << 20)
  29. file,handler,err := r.FormFile("file")
  30. if err != nil {
  31. fmt.Println(err)
  32. return
  33. }
  34. defer file.Close()
  35. baseName:= os.Args[1]
  36. f,err := os.OpenFile(baseName+handler.Filename,os.O_WRONLY|os.O_CREATE,777)
  37. if err != nil {
  38. fmt.Println(err)
  39. return
  40. }
  41. defer f.Close()
  42. io.Copy(f,file)
  43. if err != nil {
  44. fmt.Println(err)
  45. return
  46. }
  47. compilationCode,runCode,testsPositive,testsTotal := processWithDocker(baseName + handler.Filename,handler.Filename)
  48. result := Result{
  49. CompilationCode: compilationCode,RunCode: runCode,TestsPositive:testsPositive,TestsTotal:testsTotal,}
  50. resultMarshaled,_ := json.Marshal(result)
  51. w.Write(resultMarshaled)
  52. } else {
  53. w.Write([]byte("GO server is active. Use POST to submit your solution."))
  54. }
  55. }
  56. // there is assumption that docker is installed where server.go is running
  57. // and the container is already pulled
  58. // TODO: handle situation when container is not pulled
  59. // TODO: somehow capture if compilation wasn't successful and
  60. // TODO: distinguish it from possible execution / time limit / memory limit error
  61. // https://stackoverflow.com/questions/18986943/in-golang-how-can-i-write-the-stdout-of-an-exec-cmd-to-a-file
  62. func processWithDocker(filenameWithDir string,filenameWithoutDir string) (int,int,int) {
  63. ctx,cancel := context.WithTimeout(context.Background(),10*time.Second)
  64. defer cancel()
  65. cli,err := client.NewEnvClient()
  66. if err != nil {
  67. panic(err)
  68. }
  69. var hostVolumeString = filenameWithDir
  70. var hostConfigBindString = hostVolumeString + ":/WORKING_FOLDER/" + filenameWithoutDir
  71. var hostConfig = &container.HostConfig{
  72. Binds: []string{hostConfigBindString},}
  73. resp,err := cli.ContainerCreate(ctx,&container.Config{
  74. Image: "tusty53/ubuntu_c_runner:twelfth",Env: []string{"F00=" + filenameWithoutDir},Volumes: map[string]struct{}{
  75. hostVolumeString: struct{}{},},hostConfig,nil,"")
  76. if err != nil {
  77. panic(err)
  78. }
  79. if err := cli.ContainerStart(ctx,resp.ID,dockertypes.ContainerStartOptions{}); err != nil {
  80. panic(err)
  81. }
  82. fmt.Println(resp.ID)
  83. var exited = false
  84. for !exited {
  85. json,err := cli.ContainerInspect(ctx,resp.ID)
  86. if err != nil {
  87. panic(err)
  88. }
  89. exited = json.State.Running
  90. fmt.Println(json.State.Status)
  91. }
  92. normalOut,err := cli.ContainerLogs(ctx,dockertypes.ContainerLogsOptions{ShowStdout: true,ShowStderr: false})
  93. if err != nil {
  94. panic(err)
  95. }
  96. errorOut,dockertypes.ContainerLogsOptions{ShowStdout: false,ShowStderr: true})
  97. if err != nil {
  98. panic(err)
  99. }
  100. buf := new(bytes.Buffer)
  101. buf.ReadFrom(normalOut)
  102. sOut := buf.String()
  103. buf2 := new(bytes.Buffer)
  104. buf2.ReadFrom(errorOut)
  105. sErr := buf2.String()
  106. log.Printf("start\n")
  107. log.Printf(sOut)
  108. log.Printf("end\n")
  109. log.Printf("start error\n")
  110. log.Printf(sErr)
  111. log.Printf("end error\n")
  112. var testsPositive=0
  113. var testsTotal=0
  114. if(sErr!=""){
  115. return 0,0
  116. }
  117. if(sOut!=""){
  118. fmt.Sscanf(sOut,"%d %d",&testsPositive,&testsTotal)
  119. return 1,1,testsTotal
  120. }
  121. return 1,0
  122. }
  123. // Creates examine directory if it doesn't exist.
  124. // If examine directory already exists,then comes an error.
  125. func prepareDir() {
  126. cmdMkdir := exec.Command("mkdir",os.Args[1])
  127. errMkdir := cmdMkdir.Run()
  128. if errMkdir != nil {
  129. log.Println(errMkdir)
  130. }
  131. }
  132. func main() {
  133. prepareDir()
  134. go http.HandleFunc("/submission",upload)
  135. http.ListenAndServe(":8123",nil)
  136. }

Dockerfile

  1. FROM ubuntu
  2. ENV DEBIAN_FRONTEND noninteractive
  3. RUN apt-get update && \
  4. apt-get -y install gcc
  5. COPY . /WORKING_FOLDER
  6. WORKDIR /WORKING_FOLDER
  7. CMD ["./chain"]

文件

  1. #!/bin/bash
  2. gcc -Wall $F00 -o hello
  3. ./hello
  4. >&2 echo ""
最佳答案
您应该考虑将Docker CLI作为一个单独的进程运行,只需读取其stdout和stderr,例如:

  1. cmd := exec.Command("docker","run","-v=

猜你在找的Docker相关文章