这个问题已经被问过了例如Docker:服务器是否运行在主机"localhost"上?(::1)并在5432端口上接受TCP/IP连接?但是我仍然不知道如何正确地将应用程序连接到数据库。
文件:
Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY . .
RUN pip install --upgrade pip
RUN pip install "fastapi[all]" sqlalchemy psycopg2-binary
docker-compose.yml
version: '3.8'
services:
ylab:
container_name: ylab
build:
context: .
entrypoint: >
sh -c "uvicorn main:app --reload --host 0.0.0.0"
ports:
- "8000:8000"
postgres:
container_name: postgr
image: postgres:15.1-alpine
environment:
POSTGRES_DB: "fastapi_database"
POSTGRES_PASSWORD: "password"
ports:
- "5433:5432"
main.py
import fastapi as _fastapi
import sqlalchemy as _sql
import sqlalchemy.ext.declarative as _declarative
import sqlalchemy.orm as _orm
DATABASE_URL = "postgresql://postgres:password@localhost:5433/fastapi_database"
engine = _sql.create_engine(DATABASE_URL)
SessionLocal = _orm.sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = _declarative.declarative_base()
class Menu(Base):
__tablename__ = "menu"
id = _sql.Column(_sql.Integer, primary_key=True, index=True)
title = _sql.Column(_sql.String, index=True)
description = _sql.Column(_sql.String, index=True)
app = _fastapi.FastAPI()
# Create table 'menu'
Base.metadata.create_all(bind=engine)
如果我只在容器中托管postgres数据库,并且我的应用程序在本地运行,那么这个工作,但是如果数据库和应用程序在它们自己的容器中,无论我如何尝试更改设置,错误总是出现:
"sqlalchemy.exc。操作错误:(psycopg2.OperationalError)连接到"本地主机"的服务器;(127.0.0.1),端口5433失败:连接被拒绝服务器是否在该主机上运行并接受TCP/IP连接?在"localhost"连接到服务器(::1),端口5433 failed:无法分配请求的地址ylab |服务器是否在该主机上运行并接受TCP/IP连接?">
错误出现在
Base.metadata.create_all(bind=engine)
我也试过
DATABASE_URL = "postgresql://postgres:password@postgres:5433/fastapi_database"
但仍然错误:
"sqlalchemy.exc。(psycopg2.OperationalError)连接到postgresql服务器;(172.23.0.2),端口5433失败:连接拒绝ylab |服务器是否在该主机上运行并接受TCP/IP连接?">
有某种配置文件或上面的答案中提到的东西,但我不知道如何管理该配置。
您应该更新配置以引用postgres的服务名称和数据库在容器内运行的端口
DATABASE_URL = "postgresql://postgres:password@postgres:5432/fastapi_database"
当你的应用程序在本地机器上运行,数据库在容器中运行,那么localhost:5433
将工作,因为主机上的端口5433
映射到db容器内的5432
。
当你把应用程序放在自己的容器中,但仍然引用localhost,那么它将在应用程序所在的相同容器中寻找postgres数据库,这是不对的。
当你输入正确的服务名称,但是端口5433,你也会得到一个错误,因为端口5433只映射到运行容器的主机上,而不是从容器内部映射。
所以你想在应用程序容器中做的只是将数据库服务定位在端口5432上,因为这是postgres在容器内运行的端口。
你可能还想看看一个依赖脚本,它不会启动快速api应用程序,直到db准备好。