Heroku上带有乌龟ORM和FastAPI的SSL错误

2024-05-15 15:33:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Heroku上部署基本的FastAPI/Ortoise ORM应用程序(针对这个问题)时失败了

app/main.py读取

import os

from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise


app = FastAPI()

register_tortoise(
    app,
    db_url=os.environ.get("DATABASE_URL"),
    modules={"models": ["app.models"]},
    generate_schemas=True,
    add_exception_handlers=True,
)

@app.get("/")
def main():
    return "OK"

app/models.py

from tortoise import models

class Test(models.Model):
    pass

Docker文件是

FROM python:3.8.6-slim-buster

# create directory for the app user
RUN mkdir -p /home/app

# create the app user
RUN addgroup --system app && adduser --system --group app

# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install system dependencies
RUN apt-get update \
  && apt-get -y install netcat gcc postgresql \
  && apt-get clean

# add app
COPY . .

# install python dependencies
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

# chown all the files to the app user
RUN chown -R app:app $APP_HOME

# change to the app user
USER app

# run gunicorn
CMD gunicorn --bind 0.0.0.0:$PORT app.main:app -k uvicorn.workers.UvicornWorker

requirements.txt

fastapi==0.63.0
tortoise-orm[asyncpg]==0.16.19
uvicorn[standard]==0.13.1
gunicorn=20.0.4

部署后,我得到以下错误(用户和数据库都正常,我已检查)

2021-01-11T19:43:46.029946+00:00 heroku[web.1]: Starting process with command `/bin/sh -c gunicorn\ --bind\ 0.0.0.0:\51457\ app.main:app\ -k\ uvicorn.workers.UvicornWorker`
2021-01-11T19:43:53.752383+00:00 heroku[web.1]: State changed from starting to up
2021-01-11T19:43:53.237242+00:00 app[web.1]: [2021-01-11 19:43:53 +0000] [5] [INFO] Starting gunicorn 20.0.4
2021-01-11T19:43:53.238555+00:00 app[web.1]: [2021-01-11 19:43:53 +0000] [5] [INFO] Listening at: http://0.0.0.0:51457 (5)
2021-01-11T19:43:53.238813+00:00 app[web.1]: [2021-01-11 19:43:53 +0000] [5] [INFO] Using worker: uvicorn.workers.UvicornWorker
2021-01-11T19:43:53.246404+00:00 app[web.1]: [2021-01-11 19:43:53 +0000] [7] [INFO] Booting worker with pid: 7
2021-01-11T19:43:54.363305+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [7] [INFO] Started server process [7]
2021-01-11T19:43:54.364061+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [7] [INFO] Waiting for application startup.
2021-01-11T19:43:54.544530+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [7] [ERROR] Traceback (most recent call last):
2021-01-11T19:43:54.544535+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 526, in lifespan
2021-01-11T19:43:54.544537+00:00 app[web.1]: async for item in self.lifespan_context(app):
2021-01-11T19:43:54.544538+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 467, in default_lifespan
2021-01-11T19:43:54.544539+00:00 app[web.1]: await self.startup()
2021-01-11T19:43:54.544539+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 502, in startup
2021-01-11T19:43:54.544540+00:00 app[web.1]: await handler()
2021-01-11T19:43:54.544540+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/tortoise/contrib/fastapi/__init__.py", line 92, in init_orm
2021-01-11T19:43:54.544540+00:00 app[web.1]: await Tortoise.init(config=config, config_file=config_file, db_url=db_url, modules=modules)
2021-01-11T19:43:54.544541+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/tortoise/__init__.py", line 593, in init
2021-01-11T19:43:54.544541+00:00 app[web.1]: await cls._init_connections(connections_config, _create_db)
2021-01-11T19:43:54.544541+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/tortoise/__init__.py", line 390, in _init_connections
2021-01-11T19:43:54.544542+00:00 app[web.1]: await connection.create_connection(with_db=True)
2021-01-11T19:43:54.544543+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/tortoise/backends/asyncpg/client.py", line 94, in create_connection
2021-01-11T19:43:54.544543+00:00 app[web.1]: self._pool = await asyncpg.create_pool(None, password=self.password, **self._template)
2021-01-11T19:43:54.544544+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/pool.py", line 398, in _async__init__
2021-01-11T19:43:54.544544+00:00 app[web.1]: await self._initialize()
2021-01-11T19:43:54.544544+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/pool.py", line 426, in _initialize
2021-01-11T19:43:54.544545+00:00 app[web.1]: await first_ch.connect()
2021-01-11T19:43:54.544545+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/pool.py", line 125, in connect
2021-01-11T19:43:54.544545+00:00 app[web.1]: self._con = await self._pool._get_new_connection()
2021-01-11T19:43:54.544546+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/pool.py", line 468, in _get_new_connection
2021-01-11T19:43:54.544546+00:00 app[web.1]: con = await connection.connect(
2021-01-11T19:43:54.544547+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/connection.py", line 1718, in connect
2021-01-11T19:43:54.544547+00:00 app[web.1]: return await connect_utils._connect(
2021-01-11T19:43:54.544548+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/connect_utils.py", line 663, in _connect
2021-01-11T19:43:54.544548+00:00 app[web.1]: con = await _connect_addr(
2021-01-11T19:43:54.544548+00:00 app[web.1]: File "/usr/local/lib/python3.8/site-packages/asyncpg/connect_utils.py", line 642, in _connect_addr
2021-01-11T19:43:54.544549+00:00 app[web.1]: await asyncio.wait_for(connected, timeout=timeout)
2021-01-11T19:43:54.544549+00:00 app[web.1]: File "/usr/local/lib/python3.8/asyncio/tasks.py", line 491, in wait_for
2021-01-11T19:43:54.544549+00:00 app[web.1]: return fut.result()
2021-01-11T19:43:54.544551+00:00 app[web.1]: asyncpg.exceptions.InvalidAuthorizationSpecificationError: no pg_hba.conf entry for host "54.198.69.158", user "mjvjvasulvwdtk", database "d96hv3qhpn6k5b", SSL off
2021-01-11T19:43:54.544551+00:00 app[web.1]: 
2021-01-11T19:43:54.545043+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [7] [ERROR] Application startup failed. Exiting.
2021-01-11T19:43:54.545451+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [7] [INFO] Worker exiting (pid: 7)
2021-01-11T19:43:54.845958+00:00 app[web.1]: [2021-01-11 19:43:54 +0000] [12] [INFO] Booting worker with pid: 12

我在https://help.heroku.com/DR0TTWWD/seeing-fatal-no-pg_hba-conf-entry-errors-in-postgreshttps://devcenter.heroku.com/articles/heroku-postgresql#heroku-postgres-ssl找到了来自Heroku的指导,但我不知道如何添加sslmode=require(将其作为参数附加到DATABASE_URL上不起作用)

提前感谢你的帮助


Tags: inpyappinitlibpackagesusrlocal
2条回答

根据文档here,当使用URI连接数据库时,可以将ssl作为参数传递,它可以是True或自定义python ssl上下文。检查Tortoise Doc以获取自签名证书的示例

import re
import ssl
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise

config = re.match("postgres://(.*?):(.*?)@(.*?)/(.*)", URI)
DB_USER, DB_PASS, DB_HOST, DB = config.groups()

context = ssl.create_default_context(cafile="./rds-combined-ca-bundle.pem")
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE

db_config = {
    "connections": {
        "default": {
            "engine": "tortoise.backends.asyncpg",
            "credentials": {
                "database": DB,
                "host": DB_HOST.split(":")[0],
                "password": DB_PASS,
                "port": int(DB_HOST.split(":")[1]),
                "user": DB_USER,
                "ssl": context,  # Here we pass in the SSL context
            },
        }
    },
    "apps": {
        "models": {
            "models": ["app.models"],
            "default_connection": "default",
        }
    },
}
app = FastAPI()
register_tortoise(app, config=db_config)

这段代码在部署了docker的Heroku应用程序中工作ca-bundle download

相关问题 更多 >