在本教程中,将使用 Azure Cosmos DB Linux 模拟器作为本地开发数据库,生成 TypeScript 应用程序,然后通过交换凭据迁移到Azure Cosmos DB。
在本教程中,你将了解:
- 在 Docker 容器中启动Azure Cosmos DB模拟器
- 创建 TypeScript 应用程序
- 将应用程序连接到本地模拟器
- 创建 Azure Cosmos DB 帐户
- 将应用程序部署到Azure Cosmos DB
先决条件
- Node.js 22 或更高版本
- Docker Desktop
- Azure CLI
- 一份 Azure 订阅。 如果没有 Azure 订阅,可在开始前创建一个试用帐户。
启动模拟器
使用基于 Linux 的 Azure Cosmos DB 模拟器的 Docker 容器映像创建本地开发数据库。
拉取模拟器容器映像。
docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-latest启动模拟器容器。
docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmos-db mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-latest验证容器是否正在运行。
docker ps --filter "name=cosmos-db"Important
仿真器网关终结点可通过
https://localhost:8081获得,数据资源管理器可通过http://localhost:1234使用。 模拟器使用已知的身份验证密钥:AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;设置 价值 终结点 https://localhost:8081关键 C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
创建应用程序
创建 Next.js 应用程序并将其连接到本地模拟器。
在空文件夹中创建新的 Next.js 应用程序。 接受任何默认设置。
npx create-next-app .安装用于Azure Cosmos DB的 Node.js 客户端库。
npm install --save @azure/cosmos使用以下代码创建一
app/data.tsx个名为的新文件。 此文件包含与数据库交互的服务器操作。"use server"; import { CosmosClient } from "@azure/cosmos"; import { revalidatePath } from "next/cache"; const connectionString = "<cosmos-db-connection-string>"; const client = new CosmosClient(connectionString); const { database } = await client.databases.createIfNotExists({ id: "work-management" }); const { container } = await database.containers.createIfNotExists({ id: "tasks", partitionKey: "/id" }); export type Todo = { id: string; title: string; completed: boolean; }; export async function getTodos(): Promise<Todo[]> { const { resources } = await container.items .query("SELECT * FROM c ORDER BY c._ts DESC") .fetchAll(); return resources.map((doc) => ({ id: doc.id, title: doc.title, completed: doc.completed, })); } export async function addTodo(formData: FormData) { const title = formData.get("title") as string; if (!title?.trim()) return; await container.items.create({ title: title.trim(), completed: false, }); revalidatePath("/"); } export async function toggleTodo(formData: FormData) { const id = formData.get("id") as string; const { resource: doc } = await container.item(id, id).read(); if (doc) { await container.item(id, id).replace({ ...doc, completed: !doc.completed, }); } revalidatePath("/"); } export async function deleteTodo(formData: FormData) { const id = formData.get("id") as string; await container.item(id, id).delete(); revalidatePath("/"); }Important
在启动容器时,请将连接字符串占位符替换为本教程前面指定的凭据。
删除现有
app/page.tsx文件并将其替换为以下代码。import { getTodos, addTodo, toggleTodo, deleteTodo } from "./data"; export default async function Home() { const todos = await getTodos(); return ( <div className="min-h-screen bg-black text-zinc-50 font-sans"> <main className="max-w-lg mx-auto py-16 px-8"> <h1 className="text-2xl font-semibold tracking-tight mb-8">Todo App</h1> <form action={addTodo} className="flex gap-2 mb-8"> <input name="title" placeholder="Add a todo..." required className="flex-1 rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-600" /> <button type="submit" className="rounded-md bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 hover:bg-zinc-300 transition-colors"> Add </button> </form> <ul className="space-y-2"> {todos.map((todo) => ( <li key={todo.id} className="flex items-center gap-3 rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2"> <form action={toggleTodo}> <input type="hidden" name="id" value={todo.id} /> <button type="submit" className="text-lg leading-none">{todo.completed ? "✅" : "⬜"}</button> </form> <span className={`flex-1 text-sm ${todo.completed ? "line-through text-zinc-500" : "text-zinc-100"}`}>{todo.title}</span> <form action={deleteTodo}> <input type="hidden" name="id" value={todo.id} /> <button type="submit" className="text-sm text-red-400 hover:text-red-300 transition-colors">✕</button> </form> </li> ))} </ul> {todos.length === 0 && <p className="text-center text-sm text-zinc-500 mt-4">No todos yet.</p>} </main> </div> ); }在本地运行应用程序。
npm run dev在浏览器中打开
http://localhost:3000,验证应用程序是否正在运行并连接到模拟器。小窍门
可以查看此应用程序在 Azure Cosmos DB Emulator 数据资源管理器
http://localhost:1234中创建的数据。 还可以将 Azure Cosmos DB 扩展用于 Visual Studio Code 数据库名为work-management,容器命名为tasks。停止应用程序。
创建 Azure Cosmos DB 帐户
创建Azure Cosmos DB帐户以在云中托管应用程序数据。
为帐户名称和目标资源组名称创建变量。
RESOURCE_GROUP_NAME="<resource-group-name>" ACCOUNT_NAME="<account-name>"Important
将
<resource-group-name>和<account-name>替换为自己的值。 帐户名称必须具有多区域唯一性。创建Azure Cosmos DB帐户。
az cosmosdb create \ --resource-group $RESOURCE_GROUP_NAME \ --name $ACCOUNT_NAME获取帐户的连接字符串。
az cosmosdb keys list \ --resource-group $RESOURCE_GROUP_NAME \ --name $ACCOUNT_NAME \ --type connection-strings \ --query "connectionStrings[0].connectionString" \ --output tsv记录连接字符串的值。 你在下一步中使用它。
将应用程序连接到Azure Cosmos DB
更新应用程序以连接到Azure Cosmos DB而不是本地模拟器。
在
app/data.tsx中,将模拟器连接字符串替换为Azure Cosmos DB连接字符串。const connectionString = "<azure-cosmos-db-connection-string>";Important
将
<azure-cosmos-db-connection-string>替换为在上一步中记录的连接字符串。再次启动应用程序。
npm run dev在浏览器中打开
http://localhost:3000。 应用程序现在将数据读取并写入Azure Cosmos DB帐户。
清理资源
如果不再需要在本教程中创建的资源,请将其删除以避免产生费用。
删除Azure Cosmos DB帐户。
az cosmosdb delete \ --resource-group $RESOURCE_GROUP_NAME \ --name $ACCOUNT_NAME \ --yes停止并删除模拟器容器。
docker stop cosmos-db docker rm cosmos-db