如何正确配置Dockerfile以在Google Cloud Run上运行?

3
我正在尝试在Google Cloud Run上使用Docker运行Go应用程序,但我遇到了以下错误:
容器无法启动。无法启动并侦听由PORT环境变量定义的端口。此修订版的日志可能包含更多信息。
我已将端口固定为8080,如文档中所述,但我认为我的Dockerfile不正确。有人知道我错过了什么吗?最初的回答。
FROM golang:1.12-alpine

RUN apk upgrade -U \
  && apk add \
  ca-certificates \
  git \
  libva-intel-driver \
  make \
  && rm -rf /var/cache/*

ENV GOOS linux
ENV GOARCH amd64
ENV CGO_ENABLED=0
ENV GOFLAGS "-ldflags=-w -ldflags=-s"
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN echo $PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
RUN go get -u github.com/cespare/reflex
# RUN reflex -h 
# Setup modules after reflex install
ENV GO111MODULE=on \
  GOFLAGS="$GOFLAGS -mod=vendor"

WORKDIR /go/src/bitbucket.org/team/app/

COPY . .

CMD [ "go", "run", "cmd/main.go" ]

您的程序没有侦听正确的TCP端口或无法创建服务器。正确的值是PORT而不是8080。现在只是恰好是8080。您将应用程序配置为侦听哪个端口?换句话说,请展示您的代码。在您的代码中,您需要读取环境变量port:= os.Getevn(“PORT”),然后使用该值进行侦听器。此外,请在Cloud Run Console GUI或Stackdriver中检查日志以获取错误消息。 - John Hanley
2个回答

8

Dockerfile并不能使你的应用程序监听特定的端口号。

在Dockerfile中使用的EXPOSE指令纯粹是一种文档说明,不具备实际功能。

针对Go应用程序,你有两个选择:

  1. Just refactor your code to read the PORT env variable: os.Getenv("PORT") and use it on the HTTP server address you’re starting:

    port := os.Getenv("PORT")
    http.ListenAndServe(":"+port)
    
  2. Create a -port flag and read it during the entrypoint of your app in the Dockerfile:

    e.g. if you can make go run main.go -port=8080 work, change your dockerfile to:

    exec go run main.go -port=$PORT
    

以下内容可以帮助您达到您想要的目标。

理想情况下,您不应该在容器中使用go run。只需执行以下操作:

RUN go build -o /bin/my-app ./my/pkg
ENTRYPOINT /bin/my-app

要直接编译Go程序并使用它,否则每次Cloud Run启动您的容器时,都需要从头重新编译,这不是快速的,这将增加您的冷启动时间。
此外,在您的dockerfile中存在许多不一致之处。您设置了许多Go环境变量,如GOOS GOARCH,但实际上没有进行go build您的应用程序(go run是即时编译,不考虑GOFLAGS中的链接器标志)。请查看示例Go dockerfile,以更好地了解如何编写惯用的Go dockerfile。

你指引了我正确的方向,我已经接近成功了!谢谢!虽然我仍然遇到错误,但我知道这是因为我将 CMD 指向了错误的可执行文件...即我本地构建的 bin/app-name。你知道在使用 go install -v ./... 在 Cloud Build 中构建后可执行文件的路径吗? - Martavis P.
我找到了答案,希望能帮到其他人。我找到了这篇文章,它说明了go install的作用(我将其添加到了我的Dockerfile中)。它创建了二进制文件并将其放置在$GOPATH/bin中,而在Docker容器中则是/go/bin。因此,我在Dockerfile中的CMD命令现在是CMD [ "/go/bin/cmd" ],其中cmd是二进制文件名。 - Martavis P.
是的,当你执行 go build 命令时,编译器会在当前目录下创建一个二进制文件,文件名与你所构建的包名相同。如果要将二进制文件构建到自定义目录中,请使用 go build -o /path/to/bin PKG 命令。 - ahmet alp balkan

0

2
EXPOSE 做的并非是功能性操作,而只是文档说明。 - ahmet alp balkan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接