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

时间:2019-05-10 08:16:04

标签: docker go google-cloud-platform google-cloud-run

我正在尝试使用Docker在Google Cloud Run上运行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,但我认为我的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" ]

2 个答案:

答案 0 :(得分:5)

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

Dockerfile中的EXPOSE指令纯粹是一个文档,没有任何功能。

您有2个用于Go应用程序的选项:

  1. 只需重构代码即可读取PORT env变量: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 Run 启动容器时,您都会从头开始重新编译它,这不是很快,这会增加冷启动的时间。


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

答案 1 :(得分:-1)

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