Docker Compose部署Python+PostgreSQL应用时遭遇psycopg2.OperationalError: fe_sendauth: no password supplied错误
看起来你遇到的核心问题是Python应用容器没有正确读取到.env里的数据库密码,或者PostgreSQL容器初始化时没有使用正确的密码创建用户,导致连接时报密码未提供的错误。我来一步步帮你排查解决:
1. 确保Python应用容器能获取到.env中的环境变量
你当前的docker-compose.yml里,app服务没有配置env_file,导致容器内无法读取到.env文件的变量——虽然代码里用了load_dotenv,但本地路径和容器内路径不匹配,大概率找不到文件。
修改docker-compose.yml的app服务,添加env_file配置:
app : build: ./app/ container_name: todo-app ports: - 8002:8000 links: - db depends_on: - db env_file: - ./TODO-App/.env # 这里要和你的.env实际位置匹配,确保路径正确
这样容器启动时会自动加载.env里的所有变量到环境中,代码里直接用os.environ.get()就能读到。
2. 修复PostgreSQL初始化脚本的变量替换问题
你的init.sql里用了${POSTGRES_PASSWORD},但PostgreSQL官方镜像不会自动替换.sql文件中的环境变量——只有.sh脚本才会被shell解析变量。这会导致创建的用户密码是字符串${POSTGRES_PASSWORD},而不是你.env里的Aa123456。
解决方法是把init.sql改成shell脚本:
- 创建
init.sh文件,内容如下:
#!/bin/bash set -e # 使用环境变量执行SQL psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL CREATE USER IF NOT EXISTS todo_user WITH PASSWORD '$POSTGRES_PASSWORD'; CREATE DATABASE todo_db WITH OWNER todo_user; GRANT ALL PRIVILEGES ON DATABASE todo_db TO todo_user; \c todo_db todo_user; CREATE TABLE tasks( id SERIAL PRIMARY KEY, task VARCHAR NOT NULL, status VARCHAR NOT NULL # 注意你原来写的是ststus,这里修正了拼写错误 ); EOSQL
- 修改PostgreSQL的
Dockerfile,复制并赋予脚本执行权限:
FROM postgres:latest WORKDIR /app COPY init.sh /docker-entrypoint-initdb.d/init.sh RUN chmod +x /docker-entrypoint-initdb.d/init.sh EXPOSE 5432 CMD [ "postgres" ]
3. 确保PostgreSQL容器正确读取.env变量
同样,给db服务也加上env_file配置,确保它能读取到同一个.env文件的变量:
db: build: ./database/ container_name: todo-db env_file: - ./TODO-App/.env restart: always ports: - 5432:5432 volumes: - ./database/data:/var/lib/postgresql/data
4. 调试变量读取情况(可选但有用)
在Python代码里添加打印语句,确认变量是否正确读取:
import os # 打印读取到的变量,方便调试 print(f"POSTGRES_USER: {os.environ.get('POSTGRES_USER')}") print(f"POSTGRES_PASSWORD: {os.environ.get('POSTGRES_PASSWORD')}") print(f"POSTGRES_DB: {os.environ.get('POSTGRES_DB')}")
启动容器后看日志,如果这些变量是空的,说明.env路径配置有问题。
5. 清理旧数据卷,重新初始化
因为你之前可能已经创建了PostgreSQL的数据卷,旧的用户和数据库配置还在,所以需要彻底清理后重新构建:
docker-compose down -v docker-compose up --build
-v参数会删除所有关联的数据卷,确保PostgreSQL重新执行初始化脚本。
备注:内容来源于stack exchange,提问作者Dvir Horev

