我正在尝试使用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" ]
答案 0 :(得分:5)
Dockerfile不会使您的应用程序侦听特定的端口号。
Dockerfile中的EXPOSE
指令纯粹是一个文档,没有任何功能。
您有2个用于Go应用程序的选项:
只需重构代码即可读取PORT
env变量:os.Getenv("PORT")
并将其用于您要启动的HTTP服务器地址:
port := os.Getenv("PORT")
http.ListenAndServe(":"+port)
创建一个-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