在Docker容器中启动Golang Web服务器

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

Starting Golang webserver inside a Docker container

问题

我正在创建一个服务,其中包括允许用户随时启动/停止 Golang web 服务器的功能。为了在类似情况下运行 Node.js 服务器,我只需在容器启动时从批处理文件中执行 nodejs /path/to/index.js &disown。关键部分如下:

ADD gorun.sh /usr/local/bin/gorun.sh
RUN chmod +x /usr/local/bin/gorun.sh

...
ENTRYPOINT ["/bin/bash"]
CMD ["/usr/local/bin/gorun.sh"]

这个方法每次都能完美运行。在 gorun.sh 中,我有一行 nodejs /path/to/index.js & disown

现在,我尝试在类似的情况下让 Golang web 服务器运行,我认为可以尝试相同的方法。我修改了 gorun.sh 脚本如下:

#! /bin/bash
go run /path/to/index.go & disown;
ps aux | grep go

现在有个奇怪的问题。我尝试两种方式启动 Go 服务器:

  • 纯粹作为实验,我在终端中启动了一个附加到名为 gorun 的 Docker 容器。Golang 服务器立即启动,一切正常。
  • 为了更好地模拟实际情况,我在预定位置放置了一个名为 startgo.txt 的文件,然后由一个调用 gorun 的 CRON 作业来处理。这次,不幸的是,服务器没有启动。

为什么不直接从 Docker 容器的启动脚本中调用 go run /path/to/index.go & disown 呢?我也尝试过,结果相同:服务器没有启动。

我不清楚这里发生了什么。为什么 Node.js 服务器能够启动,而 Golang 服务器却完全拒绝?为什么如果我在终端中运行相同的脚本,它就能启动?

英文:

I am in the process of creating a service that, amongst other things, allows users start/stop a Golang web server at will. To get a Nodejs server running under similar circumstances I simply issue a nodejs /path/to/index.js &disown from within a batch file that I run when the container starts up. The essential bits

ADD gorun.sh /usr/local/bin/gorun.sh
RUN chmod +x /usr/local/bin/gorun.sh

...
ENTRYPOINT ["/bin/bash"]
CMD ["/usr/local/bin/gorun.sh"]

This works perfectly, every time. In gorun.sh I have the nodejs /path/to/index.js & disown line.

Now that I am trying to get a Golang web server running under similar conditions I thought I would try the same approach. I modified the gorun.sh script to read

#! /bin/bash
go run /path/to/index.go & disown;
ps aux | grep go

Now here is the odd thing. I have tried to get the Go server started in two ways

  • Purely as an experiment I started the Docker container with a terminal attached at called gorun from the terminal. The Golang server fired up right away and everything was hunky-dory.
  • To better emulate the way things work in the real world - I placed a file, startgo.txt at a pre-determined location which then gets picked up by a CRON job that calls gorun. This time round, no joy - the server does not start up.

Why not just call go run /path/to/index.go & disown from the Docker container start-up script? Tried that too, with the same result: the server does not start up.

It is not clear to me what is happening here. Why does the Nodejs server fire up whilst the Golang server refuses point blank? Why does it fire up if I run the same script from within a terminal?

答案1

得分: -3

这个问题让我在紧迫的截止日期下感到非常困扰,花了整整24小时才弄清楚发生了什么。问题相当微妙。所以,我在这里解释一下,以便任何遇到这个问题的人都能受益。

永远不要忘记:为了让Golang发挥其魔力,操作系统必须能够找到它。这就是$GOPATH环境变量的作用。如果你和我一样,你可能会在网上的某个地方按照说明进行操作。我按照Vultr上的这篇帖子中的说明进行操作。他们建议的要点如下:

echo export GOPATH=/opt/gopkg >> ~/.bashrc
echo export GOROOT=/opt/go >> ~/.bashrc
echo export PATH=$PATH:$GOROOT/bin:$GOPATH/bin >> ~/.bashrc

非常好的说明 - 谢谢Vultr。

关键问题

正如我在原始问题中提到的,让我感到困惑的是,当我在连接到Docker会话的终端会话中执行包含以下内容的批处理文件gorun时:

go run /path/to/index.go &

它可以正常工作。然而,当我尝试从在Docker会话启动时执行的bash脚本中执行它时,它却无法正常工作。

当你仔细思考一下,并查看上面Vultr说明中发生了什么,一切都变得非常明显。路径变量仅在打开交互式终端时设置!- 也就是说,当你尝试从任何旧的批处理文件(例如在启动Docker容器时运行的批处理文件)执行go dosomething指令时,路径变量并没有被设置。

如果你想让Golang在Docker容器内正常运行,在你在容器启动时运行的bash脚本的顶部,你需要执行以下命令:

export GOPATH="/opt/gopkg"; 
export GOROOT="/opt/go";   
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin; 
英文:

This issue drove me round the bend with looming deadlines and it took me a whole 24h to figure out what was happening. The problem is a rather subtle one. So here is an explanation for the benefit of anyone running into this thread.

Never forget: For Golang to deliver its magic the OS has to be able to find it. Enter the $GOPATH environment variable. If you are anything like me you will have followed instructions somewhere on the net on how to do this. I followed the instructions in this post on Vultr. The gist of what they suggest

echo export GOPATH=/opt/gopkg >> ~/.bashrc
echo export GOROOT=/opt/go >> ~/.bashrc
echo export PATH=$PATH:$GOROOT/bin:$GOPATH/bin >> ~/.bashrc

Excellent instructions - thank you Vultr.

The Key Isssue

As I mention in my original question what puzzled me was that when I executed the batch file gorun containing

go run /path/to/index.go &

from a terminal session attached to the Docker session it worked. However, when I tried to execute it from a bash script executed at the start of the Docker session it did not.

When you think about this a bit and look at what is happening in the Vultr instructions above it is all blindingly obvious. The path variables are being set ONLY WHEN AN INTERACTIVE TERMINAL IS OPEN! - i.e. NOT when you attempt to execute a go dosomething instruction from any old batch file - for instance the one you run when the Docker container is launched.

If you want to have Golang operate correctly from within a Docker container right at the top of the bash script you run on container startup you will need to issue

export GOPATH="/opt/gopkg"; 
export GOROOT="/opt/go";   
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin; 

huangapple
  • 本文由 发表于 2015年6月30日 05:05:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/31125557.html
匿名

发表评论

匿名网友

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

确定