docker - 由于用户输入导致 gcloud Docker 错误
问题描述
我正在尝试在 Google Cloud 上使用 Docker 部署 Python 应用程序
输入命令后gcloud run deploy --image gcr.io/id/name
,我收到此错误:
ERROR: (gcloud.run.deploy) Cloud Run error: 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.
日志浏览器:
TEST_MODE = input()
EOFError: EOF when reading a line
我知道错误是由于尝试接受用户输入引起的,并且使用 Dockers 这个命令解决了错误:
docker run -t -i
知道如何使用 gcloud 运行它吗?
解决方案
您的示例不运行服务器,因此 Cloud Run 不接受它。
Cloud Run期望服务器在其上运行PORT
(通常计算结果为,8080
但您不应假设这一点)。
虽然希望在 Cloud Run 上运行任意容器是合理的,但该服务希望通过 HTTP 做出响应。
一种选择是简单地将 HTTP 服务器塞入您的容器中,该服务器侦听PORT
然后在其旁边运行您的 Python 应用程序,但是 Python 是单线程的,因此不太容易做到这一点。另外,在单个容器中运行多个进程被认为是一种反模式。
因此,我提出以下建议:
重写您的应用程序以将输入作为 HTTP GET 返回:
main.py
:
from flask import Flask
app = Flask(__name__)
@app.route('/hello/<name>')
def hello(name):
return "Hello {name}".format(name=name)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
测试它:
python3 main.py
* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
注意Flask 在
localhost
(127.0.0.1
) 上运行。当我们在容器中运行它时,我们需要更改它。它正在运行8080
NAME="Freddie"
curl http://localhost:8080/hello/${NAME}
Hello Freddie
或浏览:http://localhost:8080/hello/Freddie
将其容器化:
Dockerfile
:
FROM python:3.10-rc-slim
WORKDIR /app
RUN pip install flask gunicorn
COPY main.py .
ENV PORT 8080
CMD exec gunicorn --bind 0.0.0.0:$PORT main:app
注意 除非
ENV PORT 8080
我们另外指定,否则将环境变量PORT
设置为值(我们将在接下来执行此操作)8080
注意该映像
gunicorn
用作 Flask 的运行时主机。这次 Flask 服务绑定到0.0.0.0
允许从容器外部访问它(我们需要),它使用的值PORT
然后:
# Build
docker build --tag=66458821 --file=./Dockerfile .
# Run
PORT="9999"
docker run \
--rm --interactive --tty \
--env=PORT=${PORT} \
--publish=8080:${PORT} \
66458821
[INFO] Starting gunicorn 20.0.4
[INFO] Listening at: http://0.0.0.0:9999 (1)
注意因为
--env=${PORT}
Flask 现在可以在上面运行,0.0.0.0:9999
但是我们将这个端口重新映射到8080
主机上。这只是为了显示PORT
容器现在如何使用变量
测试它(像以前一样使用命令)!
发布它并gcloud run deploy ...
测试它!
推荐阅读
- hibernate - 我可以将休眠字符串 entityGraph 与使用 org.springframework.data.jpa.repository.EntityGraph 的子图一起使用吗
- java - ThreadPoolExecutor 支持新线程而不是开源队列
- f# - 为什么声明顺序对通用成员很重要?
- hyperledger-fabric - 可以在创建 daml 合同时生成日期
- javascript - 销毁数组以删除项目时,Eslint 将变量标记为未使用
- java - 没有 Maven 和 Spring Boot 的 Vaadin 14
- javascript - 如何从数组中获取信息到消息中?
- c# - 使用 firebase 解决包引用错误和“java.exe exited with code 1”错误。赛马林
- c++ - c++ 适配器通过 emcc 用于 tensorflow.js
- python - Python 的可读性与阶乘递归的效率