You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Docker Compose部署FastAPI+PostgreSQL容器遇退出码1错误排查

解决Docker Compose中FastAPI连接PostgreSQL失败(exit code 1)的问题

问题诊断

从错误日志看,核心问题集中在三点:

  1. FastAPI容器启动后立即尝试连接PostgreSQL,但depends_on仅保证容器启动顺序,不等待数据库服务完全就绪
  2. .env文件中变量带引号,导致PostgreSQL错误解析数据库名、用户名等配置
  3. 代码存在SQL列名不匹配、注入风险,且硬编码数据库配置未读取环境变量

修复步骤

1. 修正.env文件格式

去掉变量值的引号,否则PostgreSQL会将引号作为名称的一部分,导致连接失败:

POSTGRES_PORT=5432
POSTGRES_DB=testdb
POSTGRES_USER=testuser
POSTGRES_PASSWORD=testpassword

2. 给FastAPI添加数据库连接重试机制

修改app/database.py,增加重试逻辑等待PostgreSQL服务就绪,同时改用环境变量读取配置:

import os
import sys
import time
import psycopg2


class Database:
    def __init__(self):
        self.conn = self.connect()

    def connect(self):
        """
        连接数据库,带重试机制
        """
        print("Connecting to PostgreSQL Database...")
        retries = 5
        delay = 2
        while retries > 0:
            try:
                conn = psycopg2.connect(
                    host="db",
                    dbname=os.getenv("POSTGRES_DB"),
                    user=os.getenv("POSTGRES_USER"),
                    password=os.getenv("POSTGRES_PASSWORD"),
                    port=os.getenv("POSTGRES_PORT", 5432),
                )
                print("Connected successfully!")
                return conn
            except psycopg2.OperationalError as e:
                retries -= 1
                print(f"Connection failed, {retries} retries left. Error: {e}")
                time.sleep(delay)
                delay *= 2
        print("Failed to connect after retries, exiting.")
        sys.exit(1)

    def add_user(self, id, firstname):
        cur = self.conn.cursor()
        # 使用参数化查询避免SQL注入,同时匹配表列名
        SQL = "INSERT INTO users (uid, firstname) VALUES (%s, %s);"
        data = (id, firstname)
        print(data)
        cur.execute(SQL, data)
        self.conn.commit()
        return {"status": "success", "user": {"id": id, "name": firstname}}

3. 修正数据库表与代码的列名匹配

如果要保留代码中的id参数,修改dump-postgres-test.sql的users表结构:

CREATE TABLE users (
    id int NULL,
    firstname varchar NULL
);

CREATE TABLE sites (
    sid varchar NULL,
    "location" point NULL
);

或者保持SQL表结构不变,修改add_user方法中的SQL语句为uid列(如上面代码所示)。

4. 让FastAPI容器读取环境变量

在compose.yaml的app服务中添加env_file配置,确保应用能读取.env中的变量:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - .:/app/
    depends_on:
      - db
    restart: always
    networks:
      - testNet
    env_file:  # 添加此行
      - .env
  db:
    image: "postgres:latest"
    restart: always
    expose:
      - 5432
    env_file:
      - .env
    volumes:
      - ./dump-postgres-test.sql:/docker-entrypoint-initdb.d/dummy_dump.sql
    networks:
      - testNet
networks:
  testNet:

验证PostgreSQL服务是否正常运行

方法1:进入数据库容器执行查询

  1. 查看PostgreSQL容器名称:docker ps
  2. 进入容器并连接数据库:
docker exec -it <你的db容器名称> psql -U testuser -d testdb
  1. 执行以下命令验证:
    • 查看所有表:\dt
    • 插入测试数据:INSERT INTO users (id, firstname) VALUES (1, 'TestUser');
    • 查询数据:SELECT * FROM users;

方法2:通过FastAPI接口测试

启动容器后,访问http://0.0.0.0:5000/users/add?id=99&name=Juan,返回{"status": "success", "user": {"id": 99, "name": "Juan"}}则说明连接正常。


内容的提问来源于stack exchange,提问作者jboat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:49:57