# 环境变量配置约定 DreamWeaver 只把 `backend/.env` 视为应用运行配置文件。根目录 `.env` 可以存在,但它只服务 Docker Compose 本身,不参与后端配置加载。 ## 文件职责 | 文件 | 读取方 | 放什么 | 不放什么 | | --- | --- | --- | --- | | `backend/.env` | FastAPI、Admin API、Celery worker、Celery beat、Docker 后端服务 | `SECRET_KEY`、`DATABASE_URL`、Redis/Celery URL、Provider 列表、AI key、OAuth key、Admin 账号 | Docker 镜像源、npm registry | | `.env` | Docker Compose 插值 | `PYTHON_BASE_IMAGE`、`NODE_BASE_IMAGE`、`NGINX_BASE_IMAGE`、`NPM_REGISTRY` 等镜像源/registry 覆盖 | AI key、OAuth key、`SECRET_KEY`、后端运行配置 | | `backend/.env.example` | 人读/复制模板 | `backend/.env` 的完整示例 | 真实密钥 | ## 为什么不让后端读取根目录 `.env` `pydantic-settings` 的相对 `env_file=".env"` 会受当前工作目录影响:在仓库根目录启动会读根 `.env`,在 `backend/` 目录启动会读 `backend/.env`。这会导致同一条启动命令在不同目录下使用不同配置。 当前代码在 `backend/app/core/config.py` 中固定使用绝对路径 `backend/.env`。因此后端从任意工作目录启动时都读取同一个文件。 ## Docker 演示 Docker 后端服务通过 `env_file: ./backend/.env` 读取应用配置。默认容器内地址应保持为服务名: ```env DATABASE_URL=postgresql+asyncpg://dreamweaver:dreamweaver_password@db:5432/dreamweaver_db CELERY_BROKER_URL=redis://redis:6379/0 CELERY_RESULT_BACKEND=redis://redis:6379/0 REDIS_URL=redis://redis:6379/0 ``` Postgres 容器只接收 `docker-compose.yml` 中固定的 demo 账号和数据库名,避免把 AI/OAuth key 注入基础设施容器。后端服务读取 `backend/.env` 中的 `DATABASE_URL`。需要改 Docker demo 的数据库账号时,同时修改 `docker-compose.yml` 的 `db.environment` 和 `backend/.env` 的 `DATABASE_URL`。Docker demo 固定暴露 `52432:5432` 和 `52379:6379`,本机直跑后端时按这些宿主机端口连接。 ## 本机直跑后端 本机直接运行 `uvicorn`、`celery` 或 `alembic` 时也只改 `backend/.env`,把数据库和 Redis URL 改成宿主机端口: ```env DATABASE_URL=postgresql+asyncpg://dreamweaver:dreamweaver_password@localhost:52432/dreamweaver_db CELERY_BROKER_URL=redis://localhost:52379/0 CELERY_RESULT_BACKEND=redis://localhost:52379/0 REDIS_URL=redis://localhost:52379/0 ``` ## 检查命令 ```bash # 后端实际读取哪个 env 文件 backend/.venv/bin/python - <<'PY' from app.core.config import BACKEND_ENV_FILE print(BACKEND_ENV_FILE) PY # Docker 后端容器实际环境,注意不要把输出贴到公共渠道 docker compose exec backend env | sort ```