无法使用Docker容器自动运行简单的Go Web服务器(func (*Template) Execute)。

huangapple go评论76阅读模式
英文:

Can't automatically run simple Go web server with Docker container (func (*Template) Execute)

问题

所以我正在尝试在CoreOS上的Docker容器中自动运行一个简单的“hello world”Web服务器。但是当应用程序尝试执行HTML模板时,我遇到了一个错误。

这是有问题的代码:

func GateHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Entered the GateHandler.")
    t, _ := template.ParseFiles("templates/helloworld.html")
    fmt.Println("Passed the ParseFiles.")
    err := t.Execute(w, nil)
    fmt.Println("Passed the Execute statement.")
    if err != nil {
        fmt.Println(err)
    }
}

这是我的Dockerfile:

FROM ubuntu:14.04
RUN mkdir app
ADD assets /app/assets 
ADD templates /app/templates
ADD web /app/web
ENV PORT 80
EXPOSE 80
ENTRYPOINT ["/app/web"]

当我运行docker容器并在浏览器中导航到适当的URL时,我看到以下错误:

Entered the GateHandler.
Passed the ParseFiles.
2015/03/28 00:10:53 http: panic serving 10.0.2.2:56292: runtime error: invalid memory address or nil pointer dereference
goroutine 5 [running]:
net/http.func·011()
    /usr/local/go/src/net/http/server.go:1130 +0xbb
html/template.(*Template).escape(0x0, 0x0, 0x0)
    /usr/local/go/src/html/template/template.go:56 +0x3a
html/template.(*Template).Execute(0x0, 0x7f1593124360, 0xc20804c460, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/html/template/template.go:75 +0x3d
main.GateHandler(0x7f1593124290, 0xc20804c460, 0xc20803c1a0)

然而,当我从Dockerfile中删除入口点,使用/bin/bash运行容器,并手动启动应用程序"./app/web"时,Web应用程序运行正常。看起来t.Execute()没有像应该的那样传递错误。唯一的区别是我是从docker run中启动Web应用程序,而不是在容器内手动启动它。

有什么见解吗?启动容器而不必担心手动启动Web服务器会更方便。

谢谢。

更新:

作为Go的新手,我忽略了永远不要忽略返回的错误的基本原则。修复代码后提供了更有用的信息。

Entered the GateHandler.
open templates/helloworld.html: no such file or directory
Passed the ParseFiles.
... and so on

这意味着当我使用Docker容器自动运行Web应用程序时,它找不到模板文件。仍在努力弄清楚原因。

golang-nuts帖子:https://groups.google.com/forum/#!topic/golang-nuts/j6JTFpGg6fI

英文:

So I am trying to automatically run a simple "hello world" web server in a docker container on CoreOS. But I get an error when the app tries to exectute the HTML template.

Here is the offending code:

func GateHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Entered the GateHandler.")
    t, _ := template.ParseFiles("templates/helloworld.html")
    fmt.Println("Passed the ParseFiles.")
    err := t.Execute(w, nil)
    fmt.Println("Passed the Execute statement.")
    if err != nil {
        fmt.Println(err)
    }
}

Here is my Dockerfile:

FROM ubuntu:14.04
RUN mkdir app
ADD assets /app/assets 
ADD templates /app/templates
ADD web /app/web
ENV PORT 80
EXPOSE 80
ENTRYPOINT ["/app/web"]

When I run the docker container and navigate to the appropriate URL in my browser, I see the following error:

Entered the GateHandler.
Passed the ParseFiles.
2015/03/28 00:10:53 http: panic serving 10.0.2.2:56292: runtime error: invalid memory address or nil pointer dereference
goroutine 5 [running]:
net/http.func·011()
    /usr/local/go/src/net/http/server.go:1130 +0xbb
html/template.(*Template).escape(0x0, 0x0, 0x0)
    /usr/local/go/src/html/template/template.go:56 +0x3a
html/template.(*Template).Execute(0x0, 0x7f1593124360, 0xc20804c460, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/html/template/template.go:75 +0x3d
main.GateHandler(0x7f1593124290, 0xc20804c460, 0xc20803c1a0)

... and so on.

However, when I remove the entry point from the Dockerfile, run the container with /bin/bash and manually launch the app "./app/web", the web app runs perfectly. Looks like t.Execute() is not passing up an error like it should. The only difference is that I am launching the web app from docker run as opposed to manually starting it within the container.

Any insights? It would be a lot more convenient to launch the container and not have to worry about starting the web server manually.

Thanks.

<h3>UPDATE:</h3>

Being new to Go, I ignored the fundamental principle of never ignoring returned errors. Fixing the code gave more useful information.

Entered the GateHandler.
open templates/helloworld.html: no such file or directory
Passed the ParseFiles.
... and so on

So this means that when I automatically run the web app with the Docker container, it can't find the template file. Still working on figuring out why that is.

golang-nuts post: https://groups.google.com/forum/#!topic/golang-nuts/j6JTFpGg6fI

答案1

得分: 1

这是一个工作目录的问题。在ENTRYPOINT语句之前,在Dockerfile中添加以下内容可以解决问题。

WORKDIR /app

之前,应用程序尝试在容器的根目录中运行,并且无法在GateHandler中找到具有相对路径的模板文件。

https://docs.docker.com/reference/builder/#workdir

英文:

It was a working directory issue. Adding the following to the Dockerfile prior to the ENTRYPOINT statement fixed it.

WORKDIR /app

Previously, the app was trying to run in the root directory of the container and was unable to find the template file with the relative path in the GateHandler.

https://docs.docker.com/reference/builder/#workdir

huangapple
  • 本文由 发表于 2015年3月28日 23:12:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/29318742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定