diff --git a/README.CN.md b/README.CN.md new file mode 100644 index 0000000000..c3ceb6cfaf --- /dev/null +++ b/README.CN.md @@ -0,0 +1,247 @@ +# 全栈 FastAPI 模板 + +测试 +代码覆盖率 + +## 技术栈及功能 + +- ⚡ 后端 API 使用 [**FastAPI**](https://fastapi.tiangolo.com)。 + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) 处理 Python 的 SQL 数据库交互(ORM)。 + - 🔍 [Pydantic](https://docs.pydantic.dev)(FastAPI 的依赖)负责数据验证和配置管理。 + - 💾 SQL 数据库采用 [PostgreSQL](https://www.postgresql.org)。 +- 🚀 前端使用 [React](https://react.dev)。 + - 💃 使用 TypeScript、hooks、Vite 等现代前端技术。 + - 🎨 前端组件基于 [Chakra UI](https://chakra-ui.com)。 + - 🤖 自动生成的前端客户端。 + - 🧪 使用 [Playwright](https://playwright.dev) 进行端到端测试。 + - 🦇 支持暗黑模式。 +- 🐋 使用 [Docker Compose](https://www.docker.com) 进行开发和生产环境配置。 +- 🔒 默认支持安全的密码哈希。 +- 🔑 基于 JWT(JSON Web Token)的认证机制。 +- 📫 基于电子邮件的密码找回功能。 +- ✅ 使用 [Pytest](https://pytest.org) 进行测试。 +- 📞 采用 [Traefik](https://traefik.io) 作为反向代理/负载均衡器。 +- 🚢 提供基于 Docker Compose 的部署指南,包括如何使用 Traefik 前端代理配置自动 HTTPS 证书。 +- 🏭 基于 GitHub Actions 的 CI(持续集成)和 CD(持续部署)。 + +### 仪表盘登录 + +[![API 文档](img/login.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 仪表盘 - 管理员界面 + +[![API 文档](img/dashboard.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 仪表盘 - 创建用户 + +[![API 文档](img/dashboard-create.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 仪表盘 - 数据项 + +[![API 文档](img/dashboard-items.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 仪表盘 - 用户设置 + +[![API 文档](img/dashboard-user-settings.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 仪表盘 - 暗黑模式 + +[![API 文档](img/dashboard-dark.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### 交互式 API 文档 + +[![API 文档](img/docs.png)](https://github.com/fastapi/full-stack-fastapi-template) + +## 使用方法 + +您可以 **直接 fork 或克隆** 此仓库并按需使用。 + +✨ 它开箱即用。✨ + +### 如何使用私人仓库 + +如果您希望使用私人仓库,由于 GitHub 不允许更改 fork 仓库的可见性,您无法直接 fork 此仓库。 + +但您可以按照以下步骤操作: + +- 创建一个新的 GitHub 仓库,例如 `my-full-stack`。 +- 手动克隆此仓库,并将名称设置为您想使用的项目名称,例如 `my-full-stack`: + +```bash +git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack +``` + +- 进入新目录: + +```bash +cd my-full-stack +``` + +- 将远程仓库的地址设置为您新创建的仓库,可以从 GitHub 界面复制地址,例如: + +```bash +git remote set-url origin git@github.com:octocat/my-full-stack.git +``` + +- 将此模板仓库添加为另一个 "remote",以便以后获取更新: + +```bash +git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git +``` + +- 将代码推送到您新的仓库: + +```bash +git push -u origin master +``` + +### 从原始模板更新 + +在克隆仓库并进行修改后,您可能需要从此原始模板中获取最新的更改。 + +- 确保您已将原始仓库添加为远程仓库,可以通过以下命令检查: + +```bash +git remote -v + +origin git@github.com:octocat/my-full-stack.git (fetch) +origin git@github.com:octocat/my-full-stack.git (push) +upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch) +upstream git@github.com:fastapi/full-stack-fastapi-template.git (push) +``` + +- 拉取最新的更改但不合并: + +```bash +git pull --no-commit upstream master +``` + +这会下载此模板的最新更改但不会立即提交,您可以在提交前检查所有内容是否正确。 + +- 如果存在冲突,请在编辑器中解决它们。 + +- 完成后,提交更改: + +```bash +git merge --continue +``` + +### 配置 + +您可以在 `.env` 文件中更新配置,以定制您的项目设置。 + +在部署前,至少需要更改以下配置项的值: + +- `SECRET_KEY` +- `FIRST_SUPERUSER_PASSWORD` +- `POSTGRES_PASSWORD` + +建议(并且应该)通过环境变量将这些配置从安全存储中传递。 + +详情请参阅 [deployment.md](./deployment.md) 文档。 + +### 生成密钥 + +`.env` 文件中的某些环境变量默认值为 `changethis`。 + +您需要用一个密钥替换这些默认值。可以运行以下命令生成密钥: + +```bash +python -c "import secrets; print(secrets.token_urlsafe(32))" +``` + +复制生成的内容,用作密码或密钥。运行命令多次可生成不同的安全密钥。 + +--- + +## 如何使用 - 替代方式:使用 Copier + +此仓库支持通过 [Copier](https://copier.readthedocs.io) 生成新项目。 + +Copier 会复制所有文件,询问您一些配置问题,并根据您的回答更新 `.env` 文件。 + +### 安装 Copier + +您可以通过以下命令安装 Copier: + +```bash +pip install copier +``` + +如果使用 [`pipx`](https://pipx.pypa.io/),可以通过以下方式运行: + +```bash +pipx install copier +``` + +**注意**:如果已安装 `pipx`,安装 Copier 是可选的,您可以直接运行它。 + +### 使用 Copier 生成项目 + +为您的新项目目录命名,例如 `my-awesome-project`。 + +进入目标父目录,并运行以下命令生成项目: + +```bash +copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust +``` + +如果您使用了 `pipx`,且未安装 Copier,可以直接运行: + +```bash +pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust +``` + +**注意**:`--trust` 选项是必须的,它允许执行一个 [创建后脚本](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py),以更新您的 `.env` 文件。 + +--- + +### 输入变量 + +Copier 会要求您提供一些配置数据。生成项目前,您可以先准备好这些数据。 + +但不用担心,生成后您可以随时在 `.env` 文件中修改这些设置。 + +以下是输入变量及其默认值(部分值会自动生成): + +- `project_name`:(默认值:`"FastAPI Project"`)项目名称,展示给 API 用户(在 .env 中)。 +- `stack_name`:(默认值:`"fastapi-project"`)Docker Compose 的标签和项目名(无空格,无句号)(在 .env 中)。 +- `secret_key`:(默认值:`"changethis"`)项目密钥,用于安全性(在 .env 中)。可使用上述方法生成。 +- `first_superuser`:(默认值:`"admin@example.com"`)首位超级用户的邮箱(在 .env 中)。 +- `first_superuser_password`:(默认值:`"changethis"`)首位超级用户的密码(在 .env 中)。 +- `smtp_host`:(默认值:`""`)发送邮件的 SMTP 服务器地址,可在 .env 中稍后设置。 +- `smtp_user`:(默认值:`""`)发送邮件的 SMTP 用户,可在 .env 中稍后设置。 +- `smtp_password`:(默认值:`""`)发送邮件的 SMTP 密码,可在 .env 中稍后设置。 +- `emails_from_email`:(默认值:`"info@example.com"`)发送邮件的账户,可在 .env 中稍后设置。 +- `postgres_password`:(默认值:`"changethis"`)PostgreSQL 数据库密码(在 .env 中)。可使用上述方法生成。 +- `sentry_dsn`:(默认值:`""`)Sentry 的 DSN,如果使用,可在 .env 中稍后设置。 + +--- + +## 后端开发 + +后端文档:[backend/README.md](./backend/README.CN.md) + +## 前端开发 + +前端文档:[frontend/README.md](./frontend/README.CN.md) + +## 部署 + +部署文档:[deployment.md](./deployment.CN.md) + +## 开发 + +通用开发文档:[development.md](./development.CN.md) + +内容包括使用 Docker Compose、自定义本地域名、`.env` 配置等。 + +## 更新日志 + +请查看 [release-notes.md](./release-notes.md)。 + +--- + +## 许可证 + +全栈 FastAPI 模板基于 MIT 许可证授权使用。 diff --git a/README.md b/README.md index afe124f3fb..0002b29aaf 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Test Coverage +[中文](./README.CN.md) + ## Technology Stack and Features - ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API. diff --git a/backend/README.CN.md b/backend/README.CN.md new file mode 100644 index 0000000000..a3101aabd7 --- /dev/null +++ b/backend/README.CN.md @@ -0,0 +1,172 @@ +# FastAPI 项目 - 后端 + +## 需求 + +* [Docker](https://www.docker.com/)。 +* [uv](https://docs.astral.sh/uv/) 用于 Python 包和环境管理。 + +## Docker Compose + +按照 [../development.md](../development.md) 中的指南启动本地开发环境。 + +## 一般工作流程 + +默认情况下,依赖项通过 [uv](https://docs.astral.sh/uv/) 管理,您可以访问该网站并安装它。 + +在 `./backend/` 目录下,您可以通过以下命令安装所有依赖项: + +```console +$ uv sync +``` + +然后,您可以激活虚拟环境: + +```console +$ source .venv/bin/activate +``` + +确保您的编辑器使用正确的 Python 虚拟环境,解释器路径为 `backend/.venv/bin/python`。 + +在 `./backend/app/models.py` 中修改或添加用于数据和 SQL 表的 SQLModel 模型,在 `./backend/app/api/` 中修改 API 端点,在 `./backend/app/crud.py` 中修改 CRUD(创建、读取、更新、删除)工具函数。 + +## VS Code + +已经配置好可以通过 VS Code 调试器运行后端,这样您就可以使用断点、暂停和检查变量等功能。 + +该设置也已配置好,您可以通过 VS Code 的 Python 测试标签运行测试。 + +## Docker Compose 覆盖 + +在开发过程中,您可以更改 Docker Compose 设置,这些更改仅会影响本地开发环境,修改文件 `docker-compose.override.yml`。 + +对该文件的修改只会影响本地开发环境,不会影响生产环境。因此,您可以添加帮助开发流程的“临时”更改。 + +例如,后端代码所在的目录会在 Docker 容器中同步,将您修改的代码实时复制到容器内部的目录。这样,您可以立即测试您的更改,无需重新构建 Docker 镜像。这应该仅在开发过程中使用,对于生产环境,您应该使用最新版本的后端代码构建 Docker 镜像。但在开发过程中,这允许您非常快速地迭代。 + +另外,还有一个命令覆盖,它运行 `fastapi run --reload`,而不是默认的 `fastapi run`。它启动一个单独的服务器进程(与生产环境中的多个进程不同),并在代码更改时重新加载进程。请注意,如果您有语法错误并保存 Python 文件,程序会崩溃并退出,容器也会停止。之后,您可以通过修复错误并重新运行来重启容器: + +```console +$ docker compose watch +``` + +另外,还有一个被注释掉的 `command` 覆盖,您可以取消注释并注释掉默认的命令。它使后端容器运行一个“无操作”进程,但保持容器存活。这允许您进入正在运行的容器并执行命令,例如进入 Python 解释器测试已安装的依赖项,或启动一个开发服务器,当检测到代码更改时会重新加载。 + +要进入容器并启动 `bash` 会话,您可以使用以下命令启动堆栈: + +```console +$ docker compose watch +``` + +然后,在另一个终端中,通过 `exec` 进入运行中的容器: + +```console +$ docker compose exec backend bash +``` + +您应该会看到如下输出: + +```console +root@7f2607af31c3:/app# +``` + +这意味着您已进入容器中的 `bash` 会话,以 `root` 用户身份位于 `/app` 目录下,这个目录中有一个名为 "app" 的子目录,您的代码就存放在容器内部的 `/app/app` 目录中。 + +在这里,您可以使用 `fastapi run --reload` 命令运行调试模式的实时重载服务器。 + +```console +$ fastapi run --reload app/main.py +``` + +输出应类似于: + +```console +root@7f2607af31c3:/app# fastapi run --reload app/main.py +``` + +然后按回车键。这将启动一个实时重载的服务器,检测到代码更改时会自动重载。 + +然而,如果没有检测到代码更改,但遇到语法错误,它会停止并报错。但因为容器仍在运行,并且您处于 Bash 会话中,所以可以在修复错误后通过重新运行相同的命令(按上箭头键,然后回车)来快速重启它。 + +...这一点说明了为什么让容器处于“空闲”状态并在 Bash 会话中启动实时重载服务器是很有用的。 + +## 后端测试 + +要测试后端,运行: + +```console +$ bash ./scripts/test.sh +``` + +测试使用 Pytest 运行,您可以修改并添加测试到 `./backend/app/tests/` 目录。 + +如果您使用 GitHub Actions,测试将自动运行。 + +### 测试运行堆栈 + +如果您的堆栈已经启动,并且您只想运行测试,可以使用: + +```bash +docker compose exec backend bash scripts/tests-start.sh +``` + +该 `/app/scripts/tests-start.sh` 脚本会在确保堆栈其余部分正在运行后调用 `pytest`。如果您需要将额外的参数传递给 `pytest`,您可以将它们传递给该命令,它们将被转发。 + +例如,要在遇到第一个错误时停止: + +```bash +docker compose exec backend bash scripts/tests-start.sh -x +``` + +### 测试覆盖率 + +运行测试时,会生成一个 `htmlcov/index.html` 文件,您可以在浏览器中打开它查看测试的覆盖率。 + +## 迁移 + +由于在本地开发时,您的应用目录作为卷挂载在容器内,您也可以在容器内使用 `alembic` 命令运行迁移,迁移代码会保存在您的应用目录中(而不仅仅保存在容器内)。因此,您可以将其添加到 Git 仓库中。 + +确保每次修改模型时创建一个“修订”,并使用该修订“升级”您的数据库。因为这将更新数据库中的表。否则,您的应用可能会出现错误。 + +* 在后端容器中启动交互式会话: + +```console +$ docker compose exec backend bash +``` + +* Alembic 已经配置为从 `./backend/app/models.py` 导入您的 SQLModel 模型。 + +* 修改模型后(例如,添加列),在容器内创建修订,例如: + +```console +$ alembic revision --autogenerate -m "Add column last_name to User model" +``` + +* 将在 alembic 目录中生成的文件提交到 Git 仓库。 + +* 创建修订后,运行数据库迁移(这实际上会更改数据库): + +```console +$ alembic upgrade head +``` + +如果您不想使用迁移,可以取消注释文件 `./backend/app/core/db.py` 中以如下结尾的行: + +```python +SQLModel.metadata.create_all(engine) +``` + +并注释掉文件 `scripts/prestart.sh` 中包含以下内容的行: + +```console +$ alembic upgrade head +``` + +如果您不想使用默认模型并且想从一开始就移除或修改它们,且不需要任何之前的修订,您可以删除 `./backend/app/alembic/versions/` 目录下的修订文件(`.py` 文件)。然后,按照上面的方法创建第一次迁移。 + +## 邮件模板 + +邮件模板位于 `./backend/app/email-templates/` 目录下。这里有两个目录:`build` 和 `src`。`src` 目录包含用于构建最终邮件模板的源文件。`build` 目录包含最终的邮件模板,这些模板将被应用程序使用。 + +在继续之前,确保您在 VS Code 中安装了 [MJML 扩展](https://marketplace.visualstudio.com/items?itemName=attilabuti.vscode-mjml)。 + +安装 MJML 扩展后,您可以在 `src` 目录中创建新的邮件模板。创建新的邮件模板后,打开 `.mjml` 文件,并在编辑器中打开命令面板(`Ctrl+Shift+P`),搜索 `MJML: Export to HTML`。这将把 `.mjml` 文件转换为 `.html` 文件,您现在可以将其保存在 `build` 目录中。 diff --git a/backend/README.md b/backend/README.md index 17210a2f2c..4c185a841d 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,5 +1,7 @@ # FastAPI Project - Backend +[中文](./README.CN.md) + ## Requirements * [Docker](https://www.docker.com/). diff --git a/deployment.CN.md b/deployment.CN.md new file mode 100644 index 0000000000..c7828afeeb --- /dev/null +++ b/deployment.CN.md @@ -0,0 +1,342 @@ +# FastAPI 项目 - 部署指南 + +您可以使用 Docker Compose 将项目部署到远程服务器。 + +本项目默认需要一个 **Traefik 代理** 来处理与外界的通信和 HTTPS 证书。 + +您可以使用 CI/CD(持续集成和持续部署)系统实现自动化部署,并提供了 GitHub Actions 的配置示例。 + +但在此之前需要先完成一些设置步骤。🤓 + +--- + +## 准备工作 + +1. 准备一个远程服务器并确保其可用。 +2. 将您的域名的 DNS 记录指向该服务器的 IP 地址。 +3. 为您的域名配置通配符子域(Wildcard Subdomain),例如 `*.fastapi-project.example.com`。 + 这将允许不同的组件通过不同的子域访问,如: + - `dashboard.fastapi-project.example.com` + - `api.fastapi-project.example.com` + - `traefik.fastapi-project.example.com` + - `adminer.fastapi-project.example.com` + - `staging` 环境也可以类似访问: + - `dashboard.staging.fastapi-project.example.com` + - `adminer.staging.fastapi-project.example.com` +4. 在远程服务器上安装并配置 [Docker](https://docs.docker.com/engine/install/)(需要安装 Docker Engine,而不是 Docker Desktop)。 + +--- + +## 公共 Traefik 代理 + +我们需要一个 **Traefik 代理** 来处理传入的连接和 HTTPS 证书。 + +以下步骤仅需执行一次。 + +--- + +### 配置 Traefik 的 Docker Compose 文件 + +1. 在远程服务器上创建一个目录用于存储 Traefik 的 Docker Compose 文件: + + ```bash + mkdir -p /root/code/traefik-public/ + ``` + +2. 将 Traefik 的 Docker Compose 文件复制到服务器。 + 您可以在本地终端使用 `rsync` 命令完成复制: + + ```bash + rsync -a docker-compose.traefik.yml root@your-server.example.com:/root/code/traefik-public/ + ``` + +--- + +### 创建 Traefik 公共网络 + +Traefik 需要一个名为 `traefik-public` 的 Docker **公共网络**与您的应用栈进行通信。 + +这种方式可以通过一个 Traefik 公共代理处理所有的外部通信(HTTP 和 HTTPS),并在代理后端部署一个或多个应用栈(不同域名下的服务,即便它们位于同一台服务器上)。 + +在远程服务器上运行以下命令以创建 `traefik-public` 网络: + +```bash +docker network create traefik-public +``` + +### Traefik 环境变量配置 + +Traefik 的 Docker Compose 文件需要您在终端中预先设置一些环境变量。可以在远程服务器上运行以下命令完成配置: + +1. 设置 HTTP Basic Auth 的用户名,例如: + + ```bash + export USERNAME=admin + ``` + +2. 设置 HTTP Basic Auth 的密码,例如: + + ```bash + export PASSWORD=changethis + ``` + +3. 使用 `openssl` 生成密码的“哈希值”并将其存储到环境变量中: + + ```bash + export HASHED_PASSWORD=$(openssl passwd -apr1 $PASSWORD) + ``` + + 如果需要验证哈希值是否正确,可以打印出来: + + ```bash + echo $HASHED_PASSWORD + ``` + +4. 设置服务器的域名,例如: + + ```bash + export DOMAIN=fastapi-project.example.com + ``` + +5. 设置 Let's Encrypt 的邮箱地址,例如: + + ```bash + export EMAIL=admin@example.com + ``` + + **注意**:必须使用实际邮箱地址,`@example.com` 结尾的邮箱地址将无法使用。 + +--- + +### 启动 Traefik 的 Docker Compose 服务 + +进入您在远程服务器中存放 Traefik Docker Compose 文件的目录: + +```bash +cd /root/code/traefik-public/ +``` + +确保环境变量已设置,并且 `docker-compose.traefik.yml` 文件已就位,运行以下命令启动 Traefik: + +```bash +docker compose -f docker-compose.traefik.yml up -d +``` + +--- + +## 部署 FastAPI 项目 + +在设置好 Traefik 后,您可以使用 Docker Compose 部署 FastAPI 项目。 + +**提示**:可以直接跳到有关使用 GitHub Actions 实现持续部署的部分。 + +--- + +### 环境变量配置 + +您需要首先设置一些环境变量。 + +1. 设置运行环境,默认为 `local`(用于开发环境),在部署到服务器时,可以设置为 `staging` 或 `production`: + + ```bash + export ENVIRONMENT=production + ``` + +2. 设置域名,默认为 `localhost`(用于开发环境),在部署时应使用自己的域名,例如: + + ```bash + export DOMAIN=fastapi-project.example.com + ``` + +3. 配置其他变量: + + - **`PROJECT_NAME`**:项目名称,用于 API 文档和邮件中显示。 + - **`STACK_NAME`**:Docker Compose 栈的名称,用于标签和项目名。可以为不同环境(如 `staging` 和 `production`)使用不同的值,例如 `fastapi-project-example-com` 和 `staging-fastapi-project-example-com`。 + - **`BACKEND_CORS_ORIGINS`**:允许的 CORS 来源列表,用逗号分隔。 + - **`SECRET_KEY`**:用于签发令牌的密钥。 + - **`FIRST_SUPERUSER`**:首个超级用户的邮箱地址,可用于创建其他用户。 + - **`FIRST_SUPERUSER_PASSWORD`**:首个超级用户的密码。 + - **`SMTP_HOST`**:SMTP 服务器主机地址(根据邮件服务商提供,如 Mailgun、Sparkpost、Sendgrid)。 + - **`SMTP_USER`** 和 **`SMTP_PASSWORD`**:SMTP 服务器的用户名和密码。 + - **`EMAILS_FROM_EMAIL`**:发送邮件的邮箱地址。 + - **`POSTGRES_SERVER`**:PostgreSQL 服务器的主机名,默认值为 `db`(Docker Compose 提供的默认值)。 + - **`POSTGRES_PORT`**:PostgreSQL 服务器的端口号,通常无需更改。 + - **`POSTGRES_PASSWORD`**:PostgreSQL 的密码。 + - **`POSTGRES_USER`** 和 **`POSTGRES_DB`**:分别为 PostgreSQL 用户和数据库名,通常可以保留默认值。 + - **`SENTRY_DSN`**:Sentry 的 DSN 地址(如果您使用 Sentry)。 + +--- + +## GitHub Actions 环境变量配置 + +有一些环境变量仅供 GitHub Actions 使用,您可以进行以下配置: + +1. **`LATEST_CHANGES`**:用于 GitHub Action [latest-changes](https://github.com/tiangolo/latest-changes) 自动生成基于合并 PR 的发布说明。需要个人访问令牌,详细信息请查看文档。 +2. **`SMOKESHOW_AUTH_KEY`**:用于 [Smokeshow](https://github.com/samuelcolvin/smokeshow) 管理和发布代码覆盖率。按照 Smokeshow 的说明创建(免费)认证密钥。 + +### 生成密钥 + +`.env` 文件中的某些环境变量默认值为 `changethis`。 + +您需要用密钥替换这些值。要生成密钥,可以运行以下命令: + +```bash +python -c "import secrets; print(secrets.token_urlsafe(32))" +``` + +复制生成的内容作为密码或密钥。如果需要多个密钥,可以再次运行该命令以生成新的密钥。 + +--- + +### 使用 Docker Compose 部署 + +在设置好环境变量后,可以使用以下命令通过 Docker Compose 部署项目: + +```bash +docker compose -f docker-compose.yml up -d +``` + +在生产环境中,通常不需要 `docker-compose.override.yml` 中的开发环境覆盖配置,因此明确指定仅使用 `docker-compose.yml` 文件。 + +--- + +## 持续部署(CD) + +您可以使用 GitHub Actions 自动部署项目。😎 + +可以为多个环境配置自动部署。 + +此项目已经配置了两个环境:`staging` 和 `production`。🚀 + +--- + +### 安装 GitHub Actions Runner + +1. 在远程服务器上为 GitHub Actions 创建一个用户: + + ```bash + sudo adduser github + ``` + +2. 为 `github` 用户添加 Docker 权限: + + ```bash + sudo usermod -aG docker github + ``` + +3. 临时切换到 `github` 用户: + + ```bash + sudo su - github + ``` + +4. 转到 `github` 用户的主目录: + + ```bash + cd + ``` + +5. [按照官方指南安装 GitHub Actions 自托管 Runner](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners#adding-a-self-hosted-runner-to-a-repository)。 + + 在配置过程中,系统会要求您为环境添加标签,例如 `production`,稍后也可以添加标签。 + +6. 配置完成后,指南会提示运行一个命令以启动 Runner。需要注意的是,如果进程被终止或者与服务器的连接中断,Runner 将停止运行。 + +--- + +### 将 Runner 配置为服务 + +为了确保 Runner 能在系统启动时运行并持续工作,可以将其安装为服务。具体步骤如下: + +1. 退出 `github` 用户并返回到 `root` 用户: + + ```bash + exit + ``` + + 退出后,您将返回到之前的用户,并位于之前的工作目录。 + +2. 确保成为 `root` 用户(如果尚未是): + + ```bash + sudo su + ``` + +3. 作为 `root` 用户,转到 `github` 用户主目录下的 `actions-runner` 目录: + + ```bash + cd /home/github/actions-runner + ``` + +4. 使用 `github` 用户安装自托管 Runner 服务: + + ```bash + ./svc.sh install github + ``` + +5. 启动服务: + + ```bash + ./svc.sh start + ``` + +6. 检查服务状态: + + ```bash + ./svc.sh status + ``` + +您可以在官方指南中了解更多信息:[配置自托管 Runner 应用程序为服务](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service)。 + +### 配置 Secrets + +在您的代码仓库中,为所需的环境变量配置 Secrets,包括 `SECRET_KEY` 等。您可以参考 [GitHub 官方指南](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository) 了解如何设置仓库 Secrets。 + +当前的 GitHub Actions 工作流需要以下 Secrets: + +- `DOMAIN_PRODUCTION` +- `DOMAIN_STAGING` +- `STACK_NAME_PRODUCTION` +- `STACK_NAME_STAGING` +- `EMAILS_FROM_EMAIL` +- `FIRST_SUPERUSER` +- `FIRST_SUPERUSER_PASSWORD` +- `POSTGRES_PASSWORD` +- `SECRET_KEY` +- `LATEST_CHANGES` +- `SMOKESHOW_AUTH_KEY` + +--- + +## GitHub Actions 部署工作流 + +`.github/workflows` 目录中已经配置了用于部署的 GitHub Actions 工作流,分别适用于以下环境(根据标签区分的 GitHub Actions Runner): + +- `staging`:当推送(或合并)到 `master` 分支时触发。 +- `production`:当发布一个 Release 时触发。 + +如果需要添加额外的环境,可以以这些配置为基础进行修改。 + +--- + +## URLs + +将 `fastapi-project.example.com` 替换为您的域名。 + +### 主 Traefik 仪表盘 + +Traefik UI: `https://traefik.fastapi-project.example.com` + +### 生产环境 + +- 前端:`https://dashboard.fastapi-project.example.com` +- 后端 API 文档:`https://api.fastapi-project.example.com/docs` +- 后端 API 基础 URL:`https://api.fastapi-project.example.com` +- Adminer:`https://adminer.fastapi-project.example.com` + +### 测试环境(Staging) + +- 前端:`https://dashboard.staging.fastapi-project.example.com` +- 后端 API 文档:`https://api.staging.fastapi-project.example.com/docs` +- 后端 API 基础 URL:`https://api.staging.fastapi-project.example.com` +- Adminer:`https://adminer.staging.fastapi-project.example.com` diff --git a/deployment.md b/deployment.md index eadf76ddae..af36314d31 100644 --- a/deployment.md +++ b/deployment.md @@ -1,5 +1,7 @@ # FastAPI Project - Deployment +[中文](./README.CN.md) + You can deploy the project using Docker Compose to a remote server. This project expects you to have a Traefik proxy handling communication to the outside world and HTTPS certificates. diff --git a/development.CN.md b/development.CN.md new file mode 100644 index 0000000000..7286600003 --- /dev/null +++ b/development.CN.md @@ -0,0 +1,205 @@ +# FastAPI 项目 - 开发指南 + +## Docker Compose + +* 使用 Docker Compose 启动本地开发环境: + +```bash +docker compose watch +``` + +* 启动后,您可以在浏览器中访问以下地址与项目交互: + +- 前端(通过 Docker 构建,根据路径处理路由):[http://localhost:5173](http://localhost:5173) +- 后端(基于 OpenAPI 的 JSON Web API):[http://localhost:8000](http://localhost:8000) +- 自动交互式文档(Swagger UI 提供的 OpenAPI 文档):[http://localhost:8000/docs](http://localhost:8000/docs) +- Adminer(数据库 Web 管理界面):[http://localhost:8080](http://localhost:8080) +- Traefik UI(查看代理如何处理路由):[http://localhost:8090](http://localhost:8090) + +**注意**:第一次启动时,可能需要几分钟完成准备。期间后端会等待数据库就绪并完成配置。您可以通过查看日志来监控其状态。 + +在另一个终端窗口运行以下命令查看日志: + +```bash +docker compose logs +``` + +如果需要查看特定服务的日志,请附加服务名称,例如: + +```bash +docker compose logs backend +``` + +--- + +## 本地开发 + +Docker Compose 文件配置了每个服务在 `localhost` 上的不同端口。 + +对于后端和前端,它们使用与本地开发服务器相同的端口,因此后端服务地址为 `http://localhost:8000`,前端服务地址为 `http://localhost:5173`。 + +这样,您可以关闭某个 Docker Compose 服务,启动其本地开发服务器,一切仍然正常运行,因为它们使用相同的端口。 + +例如,可以关闭 `frontend` 服务并在另一个终端中运行以下命令: + +```bash +docker compose stop frontend +``` + +然后启动本地前端开发服务器: + +```bash +cd frontend +npm run dev +``` + +或者,您也可以停止 `backend` Docker Compose 服务: + +```bash +docker compose stop backend +``` + +接着启动本地后端开发服务器: + +```bash +cd backend +fastapi dev app/main.py +``` + +## 在 `localhost.tiangolo.com` 使用 Docker Compose + +当您启动 Docker Compose 堆栈时,它默认使用 `localhost`,每个服务(后端、前端、Adminer 等)使用不同的端口。 + +当您部署到生产(或测试)环境时,每个服务将部署到不同的子域,例如后端使用 `api.example.com`,前端使用 `dashboard.example.com`。 + +在 [部署指南](deployment.md) 中,您可以阅读关于 Traefik(配置的代理)的内容。Traefik 负责根据子域将流量路由到每个服务。 + +如果您想在本地测试服务是否正常工作,可以编辑本地 `.env` 文件并修改: + +```dotenv +DOMAIN=localhost.tiangolo.com +``` + +Docker Compose 文件将使用此配置来设置服务的基础域名。 + +Traefik 会将 `api.localhost.tiangolo.com` 的流量路由到后端,将 `dashboard.localhost.tiangolo.com` 的流量路由到前端。 + +`localhost.tiangolo.com` 是一个特殊的域名,其所有子域都指向 `127.0.0.1`,因此可以用于本地开发。 + +修改完成后,重新运行以下命令: + +```bash +docker compose watch +``` + +在生产环境中部署时,Traefik 的主实例通常在 Docker Compose 配置外部。用于本地开发的 Traefik 包含在 `docker-compose.override.yml` 中,用于测试子域是否按预期工作(例如 `api.localhost.tiangolo.com` 和 `dashboard.localhost.tiangolo.com`)。 + +--- + +## Docker Compose 文件和环境变量 + +项目包含一个主要的 `docker-compose.yml` 文件,包含适用于整个堆栈的所有配置,由 `docker compose` 自动使用。 + +同时还有一个 `docker-compose.override.yml` 文件,提供开发环境的覆盖配置,例如将源代码挂载为卷。`docker compose` 会自动将该文件的配置叠加到 `docker-compose.yml` 上。 + +这些 Docker Compose 文件会使用 `.env` 文件中的配置,将其作为环境变量注入容器中。 + +此外,还会使用一些在运行 `docker compose` 命令前由脚本设置的环境变量。 + +在修改环境变量后,请重新启动堆栈: + +```bash +docker compose watch +``` + +--- + +## `.env` 文件 + +`.env` 文件包含所有配置、生成的密钥和密码等。 + +根据您的工作流程,可能需要将其排除在 Git 版本控制之外,例如项目是公开的情况下。在这种情况下,您需要确保为 CI 工具设置获取 `.env` 文件的方法,以便在构建或部署时使用。 + +一种方法是将每个环境变量添加到您的 CI/CD 系统中,并更新 `docker-compose.yml` 文件以读取这些特定的环境变量,而不是直接从 `.env` 文件读取。 + +--- + +## 预提交钩子和代码格式化 + +项目使用 [pre-commit](https://pre-commit.com/) 工具来进行代码格式化和检查。 + +安装后,该工具会在每次 Git 提交之前运行,从而确保代码一致且格式化良好。 + +项目根目录中有 `.pre-commit-config.yaml` 文件,包含 pre-commit 的配置。 + +--- + +### 安装 pre-commit 以自动运行 + +`pre-commit` 已作为项目依赖项的一部分,但您也可以选择按照 [官方文档](https://pre-commit.com/) 的说明全局安装它。 + +在安装并使 `pre-commit` 工具可用后,需要将其“安装”到本地仓库,以便在每次提交之前自动运行。 + +如果使用 `uv`,可以通过以下命令完成: + +```bash +❯ uv run pre-commit install +pre-commit installed at .git/hooks/pre-commit +``` + +现在,当您尝试提交时,例如运行: + +```bash +git commit +``` + +pre-commit 会运行并检查、格式化您要提交的代码,并要求您使用 Git 再次添加代码(暂存)后再提交。 + +然后,您可以通过 `git add` 添加已修改/修复的文件,再次提交即可。 + +#### 手动运行 pre-commit 钩子 + +您也可以手动运行 `pre-commit` 钩子,检查所有文件。使用 `uv` 可以执行以下命令: + +```bash +❯ uv run pre-commit run --all-files +check for added large files..............................................Passed +check toml...............................................................Passed +check yaml...............................................................Passed +ruff.....................................................................Passed +ruff-format..............................................................Passed +eslint...................................................................Passed +prettier.................................................................Passed +``` + +--- + +## URL 列表 + +生产或测试环境的 URL 将使用相同的路径,但域名会替换为您自己的。 + +### 开发环境 URL + +用于本地开发的 URL。 + +- **前端**: [http://localhost:5173](http://localhost:5173) +- **后端**: [http://localhost:8000](http://localhost:8000) +- **自动交互式文档 (Swagger UI)**: [http://localhost:8000/docs](http://localhost:8000/docs) +- **自动备用文档 (ReDoc)**: [http://localhost:8000/redoc](http://localhost:8000/redoc) +- **Adminer**: [http://localhost:8080](http://localhost:8080) +- **Traefik UI**: [http://localhost:8090](http://localhost:8090) +- **MailCatcher**: [http://localhost:1080](http://localhost:1080) + +--- + +### 配置了 `localhost.tiangolo.com` 的开发环境 URL + +用于本地开发的 URL。 + +- **前端**: [http://dashboard.localhost.tiangolo.com](http://dashboard.localhost.tiangolo.com) +- **后端**: [http://api.localhost.tiangolo.com](http://api.localhost.tiangolo.com) +- **自动交互式文档 (Swagger UI)**: [http://api.localhost.tiangolo.com/docs](http://api.localhost.tiangolo.com/docs) +- **自动备用文档 (ReDoc)**: [http://api.localhost.tiangolo.com/redoc](http://api.localhost.tiangolo.com/redoc) +- **Adminer**: [http://localhost.tiangolo.com:8080](http://localhost.tiangolo.com:8080) +- **Traefik UI**: [http://localhost.tiangolo.com:8090](http://localhost.tiangolo.com:8090) +- **MailCatcher**: [http://localhost.tiangolo.com:1080](http://localhost.tiangolo.com:1080) \ No newline at end of file diff --git a/development.md b/development.md index d7d41d73f1..204e3bdcbe 100644 --- a/development.md +++ b/development.md @@ -1,5 +1,7 @@ # FastAPI Project - Development +[中文](./README.CN.md) + ## Docker Compose * Start the local stack with Docker Compose: diff --git a/frontend/README.CN.md b/frontend/README.CN.md new file mode 100644 index 0000000000..c5afcbf895 --- /dev/null +++ b/frontend/README.CN.md @@ -0,0 +1,163 @@ +# FastAPI 项目 - 前端 + +前端是使用 [Vite](https://vitejs.dev/)、[React](https://reactjs.org/)、[TypeScript](https://www.typescriptlang.org/)、[TanStack Query](https://tanstack.com/query)、[TanStack Router](https://tanstack.com/router) 和 [Chakra UI](https://chakra-ui.com/) 构建的。 + +## 前端开发 + +在开始之前,确保您的系统上已安装 Node 版本管理器(nvm)或 Fast Node 管理器(fnm)。 + +* 要安装 fnm,请按照 [官方 fnm 安装指南](https://github.com/Schniz/fnm#installation) 操作。如果您更喜欢 nvm,可以使用 [官方 nvm 安装指南](https://github.com/nvm-sh/nvm#installing-and-updating) 进行安装。 + +* 安装了 nvm 或 fnm 后,进入 `frontend` 目录: + +```bash +cd frontend +``` + +* 如果 `.nvmrc` 文件中指定的 Node.js 版本未安装在您的系统上,您可以使用相应的命令进行安装: + +```bash +# 使用 fnm +fnm install + +# 使用 nvm +nvm install +``` + +* 安装完成后,切换到已安装的版本: + +```bash +# 使用 fnm +fnm use + +# 使用 nvm +nvm use +``` + +[中文](./README.CN.md) + +* 在 `frontend` 目录中,安装所需的 NPM 包: + +```bash +npm install +``` + +* 然后使用以下 `npm` 脚本启动实时服务器: + +```bash +npm run dev +``` + +* 然后在浏览器中打开 http://localhost:5173/。 + +请注意,这个实时服务器并没有在 Docker 内部运行,它是为本地开发设计的,这是推荐的工作流程。一旦您对前端满意,您可以构建前端 Docker 镜像并启动它,以在类似生产的环境中进行测试。但每次更改时都构建镜像并不像运行本地开发服务器和实时重载那样高效。 + +查看 `package.json` 文件以查看其他可用选项。 + +### 移除前端 + +如果您正在开发一个仅 API 的应用,并且希望移除前端,您可以轻松完成: + +* 删除 `./frontend` 目录。 + +* 在 `docker-compose.yml` 文件中,删除整个 `frontend` 服务/部分。 + +* 在 `docker-compose.override.yml` 文件中,删除整个 `frontend` 服务/部分。 + +完成后,您就得到了一个没有前端的(仅 API)应用。🤓 + +--- + +如果需要,您还可以从以下文件中移除 `FRONTEND` 环境变量: + +* `.env` +* `./scripts/*.sh` + +但是,这样做仅仅是为了清理,保留这些变量不会产生任何实际影响。 + +## 生成客户端 + +### 自动生成 + +* 激活后端虚拟环境。 +* 在项目的顶层目录下,运行脚本: + +```bash +./scripts/generate-frontend-client.sh +``` + +* 提交更改。 + +### 手动生成 + +* 启动 Docker Compose 堆栈。 + +* 从 `http://localhost/api/v1/openapi.json` 下载 OpenAPI JSON 文件,并将其复制到 `frontend` 目录的根目录下,命名为 `openapi.json`。 + +* 为了简化生成的前端客户端代码中的名称,通过运行以下脚本修改 `openapi.json` 文件: + +```bash +node modify-openapi-operationids.js +``` + +* 生成前端客户端,运行: + +```bash +npm run generate-client +``` + +* 提交更改。 + +请注意,每当后端发生更改(更改 OpenAPI 模式)时,您应该再次按照这些步骤来更新前端客户端。 + +## 使用远程 API + +如果您希望使用远程 API,可以将环境变量 `VITE_API_URL` 设置为远程 API 的 URL。例如,您可以在 `frontend/.env` 文件中设置: + +```env +VITE_API_URL=https://api.my-domain.example.com +``` + +然后,当您运行前端时,它将使用该 URL 作为 API 的基础 URL。 + +## 代码结构 + +前端代码的结构如下: + +* `frontend/src` - 主要的前端代码。 +* `frontend/src/assets` - 静态资源。 +* `frontend/src/client` - 生成的 OpenAPI 客户端。 +* `frontend/src/components` - 前端的不同组件。 +* `frontend/src/hooks` - 自定义 hooks。 +* `frontend/src/routes` - 前端的不同路由,包括页面。 +* `theme.tsx` - Chakra UI 自定义主题。 + +## 使用 Playwright 进行端到端测试 + +前端包含了使用 Playwright 进行的初步端到端测试。要运行测试,您需要确保 Docker Compose 堆栈正在运行。使用以下命令启动堆栈: + +```bash +docker compose up -d --wait backend +``` + +然后,您可以使用以下命令运行测试: + +```bash +npx playwright test +``` + +您还可以以 UI 模式运行测试,以便看到浏览器并与其进行交互: + +```bash +npx playwright test --ui +``` + +要停止并移除 Docker Compose 堆栈并清理测试中创建的数据,请使用以下命令: + +```bash +docker compose down -v +``` + +要更新测试,导航到测试目录并修改现有的测试文件,或者根据需要添加新的测试文件。 + +有关编写和运行 Playwright 测试的更多信息,请参考官方 [Playwright 文档](https://playwright.dev/docs/intro)。 \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index fde8267842..4e4cbd5c6e 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,5 +1,7 @@ # FastAPI Project - Frontend +[中文](./README.CN.md) + The frontend is built with [Vite](https://vitejs.dev/), [React](https://reactjs.org/), [TypeScript](https://www.typescriptlang.org/), [TanStack Query](https://tanstack.com/query), [TanStack Router](https://tanstack.com/router) and [Chakra UI](https://chakra-ui.com/). ## Frontend development