Google Cloud Run 不加载 .env 文件

Posted

技术标签:

【中文标题】Google Cloud Run 不加载 .env 文件【英文标题】:Google Cloud Run does not load .env file 【发布时间】:2021-07-01 04:45:22 【问题描述】:

过去几天我试图找出我做错了什么,但我仍然无法弄清楚,因为我可以使用 flask run 在本地运行应用程序,也可以使用 docker-compose up --build 使用 Docker。 Source code is here

我的问题是我的 Cloud Run 部署成功,但单击 URL 时服务不可用。我检查了日志,似乎我的环境变量没有正确加载:

line 7, in <module> from web_messaging.blueprints.user import user File 
"/web_messaging/web_messaging/blueprints/user/__init__.py", line 1, in <module> from 
web_messaging.blueprints.user.views import user File 
"/web_messaging/web_messaging/blueprints/user/views.py", line 3, in <module> from 
web_messaging.extensions import mongo, login_manager, c, bc File 
"/web_messaging/web_messaging/extensions.py", line 18, in <module> twilio_client = Client(TWILIO_SID,
TWILIO_TOKEN) File "/usr/local/lib/python3.9/site-packages/twilio/rest/__init__.py", line 54, in __init__
raise TwilioException("Credentials are required to create a TwilioClient") 
twilio.base.exceptions.TwilioException: Credentials are required to create a TwilioClient    

我有一个config/.env 文件和一个config/settings.py。我正在使用config/settings.py 上的load_dotenv().env 加载环境变量。我决定在我的config/settings.py 中添加一些 print 和 try/expect 语句来查看变量的值。

settings.py

import os
from dotenv import load_dotenv
BASEDIR = os.path.abspath(os.path.dirname(__file__))

try:
    load_dotenv(os.path.join(BASEDIR, '.env'))
    print("OK")
    print(BASEDIR)
except Exception as e:
    print(str(e))

# Mongo Database
MONGO_URI = os.getenv('MONGO_URI')
TWILIO_SID = os.getenv('TWILIO_SID')
TWILIO_TOKEN = os.getenv('TWILIO_TOKEN')
print(MONGO_URI)
print(TWILIO_SID)

当我使用 flask run、docker-compose 或 cloud-run 运行时:

BASEDIR 的值为/web_messaging/config load_dotenv() 通话期间没有异常

但是,有一个主要区别,它是我的环境变量的值,例如MONGO_URITWILIO_SID。这些变量在使用 flask rundocker-compose 时具有正确的值,但在 Cloud Run 日志中却没有。在 Cloud Run 上,这些变量等于 None

当我不使用 .env 并直接将我的变量值放入 /config/settings.py 时,没有问题,我的 Cloud Run 链接工作正常。我还尝试将 .env 移到配置文件之外和其他几个位置,但我仍然遇到同样的问题。

.
├── requirements.txt
├── Dockerfile
├── Docker-compose.yml
├── config    
│   ├── .env                           
│   ├── settings.py            
│   ├── gunicorn.py 
│   └── __init__.py 
├── web_messaging                   
│   ├── app.py      # where I am calling create_app() - factory pattern         
│   ├── blueprints              
│   ├── static                     
│   └── ...                 
└── ...

Dockerfile

FROM python:3.9-slim

ENV INSTALL_PATH /web_messaging
RUN mkdir -p $INSTALL_PATH

WORKDIR $INSTALL_PATH

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD gunicorn -b 0.0.0.0:8080 --access-logfile - "web_messaging.app:create_app()"

docker-compose.yml

version: '2'

services:
  website:
    build: .
    command: >
      gunicorn -b 0.0.0.0:8080
        --access-logfile -
        --reload
        "web_messaging.app:create_app()"
    environment:
      PYTHONUNBUFFERED: 'true'
    volumes:
      - '.:/web_messaging'
    ports:
      - '8080:8080'

config/.env

COMPOSE_PROJECT_NAME=web_messaging
FLASK_SECRET=xxx
MONGO_URI=mongodb+srv://xxx
MONGO_DB=xxx
TWILIO_SID=xxx
TWILIO_TOKEN=xxx 

config/settings.py

import os
from dotenv import load_dotenv
BASEDIR = os.path.abspath(os.path.dirname(__file__))


load_dotenv(os.path.join(BASEDIR, '.env'))

DEBUG = True
PYTHONDONTWRITEBYTECODE=1
#SERVER_NAME = '127.0.0.1:5000'


# Mongo Database
MONGO_DBNAME = os.getenv('MONGO_DB')
MONGO_URI = os.getenv('MONGO_URI')


# Twilio API 
FLASK_SECRET = os.getenv('FLASK_SECRET')
TWILIO_SID = os.getenv('TWILIO_SID')
TWILIO_TOKEN = os.getenv('TWILIO_TOKEN')
                                    

config/gunicorn.py

bind = '0.0.0.0:8080'
accesslog = '-'
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" in %(D)sµs'
                              

【问题讨论】:

如果你在本地构建和运行容器,你有同样的问题吗?我说的是容器,而不是 docker-compose,执行 docker build 然后 docker run。 嗨 Guillaume,刚刚尝试使用 docker built -t 然后 docker run 并且它有效。这是我的源代码:github.com/Pierre-Alexandre35/messaging-service-mousset 为了更清楚,我做了docker build -t helloworld . 然后docker run -p 8080:8080 -it helloworld 并且它起作用了 重现和缩小代码库的问题并不容易。就我而言,我不能将 dotenv 与 gunicorn run 一起使用。我不知道为什么(而且我不是 python 专家!)。但是为什么我在没有 gunicorn 的情况下在 Cloud Run 上使用 dotenv,效果很好。 【参考方案1】:

已修复,我确实找到了问题所在,但我不知道为什么。

当我构建自己的图像之前,将图像推送到 GCP 容器注册表中时,它起作用了:

  docker-compose up --build
  docker tag 52e6159b6b13 gcr.io/mousset005/zoro
  gcloud auth configure-docker
  docker push gcr.io/mousset005/zoro

但是,我正在做的是使用 GCP API(这是他们在 Cloud Run Python 快速入门中推荐的)使用该命令构建我的图像:

gcloud run deploy --image gcr.io/mousset005/zoro --platform managed

【讨论】:

你能告诉我这里是如何使用 .env 文件的吗? gcloud run 是如何获取 .env 文件的

以上是关于Google Cloud Run 不加载 .env 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中使用在 Google Cloud Run Dashboard 上声明的 ENV 变量

Docker 映像在本地部署,但在 Google Cloud Run 上失败

使用 GRPC 与 Google Cloud Run 通信的 Google App Engine 给出“错误:14 不可用:连接已断开”

Google Cloud Run(完全托管):无法自定义域映射

Google Cloud Run 一遍又一遍地错误运行

GCP - 无法在 Cloud Run 中使用 Google Secret Manager (@google-cloud/secret-manager)