如何将 Dockerfile 正确配置为 运行 on Google Cloud 运行?

How to configure Dockerfile correctly to run on Google Cloud Run?

我正在尝试 运行 在 Google Cloud 运行 上使用 Docker 的 Go 应用程序,但我收到此错误:

Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable. Logs for this revision might contain more information.

我按照文档中的说明将我的端口固定为 8080,但我认为我的 Docker 文件不正确。有谁知道我错过了什么?

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" ]

您的 Dockerfile 中似乎缺少 EXPOSE。参见 https://docs.docker.com/engine/reference/builder/#expose

Dockerfile 不会让您的应用程序侦听特定端口号。

Dockerfile 中的 EXPOSE 指令纯粹是一个文档,不执行任何功能。

Go 应用程序有 2 个选项:

  1. 只需重构您的代码以读取 PORT 环境变量:os.Getenv("PORT") 并在您开始的 HTTP 服务器地址上使用它:

    port := os.Getenv("PORT")
    http.ListenAndServe(":"+port)
    
  2. 创建一个 -port 标志并在 Dockerfile 中您的应用程序的入口点期间读取它:

    例如如果您可以使 go run main.go -port=8080 工作,请将您的 dockerfile 更改为:

    exec go run main.go -port=$PORT
    

这些会让你得到你想要的。

理想情况下,您不应在容器内使用go run。只需做:

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

编译一个Go程序,直接使用。否则,每次 Cloud 运行 启动你的容器,你会 re-compiling 从头开始​​,这并不快,这会增加你的 冷启动次。


除此之外,您的 dockerfile 中似乎还有很多不一致之处。你设置了很多像 GOOS GOARCH 这样的 Go 环境变量,但你实际上并没有 go build 你的应用程序(go run 是一个 on-the-fly 编译并且没有考虑 GOFLAGS 中的链接器标志我相信)。查看示例 Go dockerfiles 以更好地了解如何编写惯用的 Go dockerfiles。