使用 AZD 部署 Microsoft SQL 数据库和 Web 应用 ⏱️ 预计时间:20-30 分钟 | 预计费用:约 $15-25/月 | ⭐ 复杂度:中级 这个完整的、可运行的示例展示了如何使用 Azure Developer CLI (azd) 将一个基于 Python Flask 的 Web 应用和 Microsoft SQL 数据库部署到 Azure。所有代码均已包含并经过测试,无需外部依赖。
⏱️ 预计时间:20-30 分钟 | 预计费用:约 $15-25/月 | ⭐ 复杂度:中级
这个完整的、可运行的示例展示了如何使用 Azure Developer CLI (azd) 将一个基于 Python Flask 的 Web 应用和 Microsoft SQL 数据库部署到 Azure。所有代码均已包含并经过测试,无需外部依赖。
通过完成此示例,你将学会:
azd 命令完全自动化开始之前,请确认已安装以下工具:
Azure CLI(版本 2.50.0 或更高)
az --version # 预期输出:azure-cli 2.50.0或更高版本
Azure Developer CLI (azd)(版本 1.0.0 或更高)
azd version # 预期输出:azd版本1.0.0或更高
Python 3.8+(用于本地开发)
python --version # 预期输出:Python 3.8或更高版本
Docker(可选,用于本地容器化开发)
docker --version # 预期输出:Docker版本20.10或更高
这是一个中级示例。你需要熟悉:
AZD 新手? 请先阅读 入门指南。
此示例部署了一个包含 Web 应用和 SQL 数据库的两层架构:
┌─────────────────┐ ┌──────────────────────┐ │ User Browser │◄──────►│ Azure Web App │ └─────────────────┘ │ (Flask API) │ │ - /health │ │ - /products │ └──────────┬───────────┘ │ │ Secure Connection │ (Encrypted) │ ┌──────────▼───────────┐ │ Azure SQL Database │ │ - Products table │ │ - Sample data │ └──────────────────────┘
资源部署:
类比:可以将其想象成一家餐厅(Web 应用)和一个冷库(数据库)。顾客从菜单(API 端点)点餐,厨房(Flask 应用)从冷库(数据库)取出食材。餐厅经理(Application Insights)记录所有发生的事情。
此示例包含所有文件,无需外部依赖:
examples/database-app/ │ ├── README.md # This file ├── azure.yaml # AZD configuration file ├── .env.sample # Sample environment variables ├── .gitignore # Git ignore patterns │ ├── infra/ # Infrastructure as Code (Bicep) │ ├── main.bicep # Main orchestration template │ ├── abbreviations.json # Azure naming conventions │ └── resources/ # Modular resource templates │ ├── sql-server.bicep # SQL Server configuration │ ├── sql-database.bicep # Database configuration │ ├── app-service-plan.bicep # Hosting plan │ ├── app-insights.bicep # Monitoring setup │ └── web-app.bicep # Web application │ └── src/ └── web/ # Application source code ├── app.py # Flask REST API ├── requirements.txt # Python dependencies └── Dockerfile # Container definition
每个文件的作用:
git clone https://github.com/microsoft/AZD-for-beginners.git cd AZD-for-beginners/examples/database-app
✓ 成功检查:确认你能看到 azure.yaml 和 infra/ 文件夹:
ls # 预期:README.md, azure.yaml, infra/, src/
azd auth login
这会打开浏览器进行 Azure 身份验证。使用你的 Azure 凭据登录。
✓ 成功检查:你应该看到:
Logged in to Azure.
azd init
发生了什么:AZD 为你的部署创建了本地配置。
你会看到的提示:
dev,myapp)eastus,westeurope)✓ 成功检查:你应该看到:
SUCCESS: New project initialized!
azd provision
发生了什么:AZD 部署了所有基础设施(需要 5-8 分钟):
你会被提示输入:
sqladmin)✓ 成功检查:你应该看到:
SUCCESS: Your application was provisioned in Azure in X minutes Y seconds. You can view the resources created under the resource group rg-<env-name> in Azure Portal: https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/rg-<env-name>
⏱️ 时间:5-8 分钟
azd deploy
发生了什么:AZD 构建并部署了你的 Flask 应用:
✓ 成功检查:你应该看到:
SUCCESS: Your application was deployed to Azure in X minutes Y seconds. You can view the resources created under the resource group rg-<env-name> in Azure Portal: https://portal.azure.com/#@/resource/subscriptions/.../resourceGroups/rg-<env-name>
⏱️ 时间:3-5 分钟
azd browse
这会在浏览器中打开已部署的 Web 应用,地址为 https://app-<unique-id>.azurewebsites.net
✓ 成功检查:你应该看到 JSON 输出:
{ "message": "Welcome to the Database App API", "endpoints": { "/": "This help message", "/health": "Health check endpoint", "/products": "List all products", "/products/<id>": "Get product by ID" } }
健康检查(验证数据库连接):
curl https://app-<your-id>.azurewebsites.net/health
预期响应:
{ "status": "healthy", "database": "connected" }
列出产品(示例数据):
curl https://app-<your-id>.azurewebsites.net/products
预期响应:
[ { "id": 1, "name": "Laptop", "description": "High-performance laptop", "price": 1299.99, "created_at": "2025-11-19T10:30:00" }, ... ]
获取单个产品:
curl https://app-<your-id>.azurewebsites.net/products/1
✓ 成功检查:所有端点返回 JSON 数据且无错误。
** 恭喜!** 你已成功使用 AZD 将带有数据库的 Web 应用部署到 Azure。
密钥通过 Azure 应用服务配置安全管理——从不硬编码在源代码中。
由 AZD 自动配置:
SQL_CONNECTION_STRING:带加密凭据的数据库连接APPLICATIONINSIGHTS_CONNECTION_STRING:监控遥测端点SCM_DO_BUILD_DURING_DEPLOYMENT:启用自动依赖安装密钥存储位置:
azd provision 期间,你通过安全提示提供 SQL 凭据.azure/<env-name>/.env 文件中(已被 git 忽略)os.getenv() 读取它们为了本地测试,从示例创建 .env 文件:
cp .env.sample .env # 使用本地数据库连接编辑 .env
本地开发工作流:
# 安装依赖项 cd src/web pip install -r requirements.txt # 设置环境变量 export SQL_CONNECTION_STRING="your-local-connection-string" # 运行应用程序 python app.py
本地测试:
curl http://localhost:8000/health # 预期: {"status": "healthy", "database": "connected"}
所有 Azure 资源都在 Bicep 模板(infra/ 文件夹)中定义:
自定义示例:
要更改数据库层级,编辑 infra/resources/sql-database.bicep:
sku: { name: 'Standard' // Changed from 'Basic' tier: 'Standard' capacity: 10 }
此示例遵循 Azure 安全最佳实践:
.env 文件通过 .gitignore 排除在 Git 之外升级到托管身份(用于生产环境):
生产前安全检查清单:
每月预计费用(截至 2025 年 11 月):
| 资源 | SKU/层级 | 预计费用 |
|---|---|---|
| 应用服务计划 | B1(基本) | ~$13/月 |
| SQL 数据库 | 基本(2GB) | ~$5/月 |
| Application Insights | 按需付费 | ~$2/月(低流量) |
| 总计 | ~$20/月 |
** 节省成本的技巧**:
学习时使用免费层:
不使用时停止资源:
# 停止网络应用程序(数据库仍会收费) az webapp stop --name <app-name> --resource-group <rg-name> # 需要时重新启动 az webapp start --name <app-name> --resource-group <rg-name>
测试后删除所有资源:
azd down
这会删除所有资源并停止费用。
成本监控:
azd-env-name 标签跟踪所有资源免费层替代方案:
为了学习目的,你可以修改 infra/resources/app-service-plan.bicep:
sku: { name: 'F1' // Free tier tier: 'Free' }
注意:免费层有一些限制(每天 60 分钟 CPU,无“始终在线”功能)。
此示例包含 Application Insights 以实现全面监控:
监控内容:
访问 Application Insights:
rg-<env-name>)appi-<unique-id>)有用的查询(Application Insights → 日志):
查看所有请求:
requests | where timestamp > ago(1h) | order by timestamp desc | project timestamp, name, url, resultCode, duration
查找错误:
exceptions | where timestamp > ago(24h) | order by timestamp desc | project timestamp, type, outerMessage, operation_Name
检查健康端点:
requests | where name contains "health" | summarize count() by resultCode, bin(timestamp, 1h)
SQL 数据库审计已启用,以跟踪:
访问审计日志:
查看实时指标:
设置警报:
为关键事件创建警报:
示例警报创建:
az monitor metrics alert create \ --name "High-Response-Time" \ --resource-group <rg-name> \ --scopes <app-insights-resource-id> \ --condition "avg requests/duration > 2000" \ --description "Alert when response time exceeds 2 seconds"
azd provision 失败并显示“位置不可用”症状:
Error: The subscription is not registered for the resource type 'components' in the location 'centralus'.
解决方案:
选择其他 Azure 区域或注册资源提供程序:
az provider register --namespace Microsoft.Insights
症状:
pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider...')
解决方案:
azd provision 时输入的 SQL 管理员密码是否正确验证连接:
# 从 Azure 门户,转到 SQL 数据库 → 查询编辑器 # 尝试使用您的凭据连接
症状:
浏览器显示通用错误页面。
解决方案:
检查应用程序日志:
# 查看最近的日志 az webapp log tail --name <app-name> --resource-group <rg-name>
常见原因:
azd deploy 失败并显示“构建错误”症状:
Error: Failed to build project
解决方案:
requirements.txt 没有语法错误infra/resources/web-app.bicep 中是否指定了 Python 3.11本地调试:
cd src/web docker build -t test-app . docker run -p 8000:8000 test-app
症状:
ERROR: (Unauthorized) The client '<id>' with object id '<id>' does not have authorization
解决方案:
重新认证 Azure:
azd auth login az login
验证您是否在订阅中具有正确的权限(Contributor 角色)。
症状:
意外的 Azure 账单。
解决方案:
azd down查看所有 AZD 环境变量:
azd env get-values
检查部署状态:
az webapp show --name <app-name> --resource-group <rg-name> --query state
访问应用程序日志:
az webapp log download --name <app-name> --resource-group <rg-name> --log-file app-logs.zip
需要更多帮助?
目标:确认所有资源已部署且应用程序正常运行。
步骤:
列出资源组中的所有资源:
az resource list --resource-group rg-<env-name> --output table
预期结果:6-7 个资源(Web App、SQL Server、SQL 数据库、App Service 计划、Application Insights、Log Analytics)
测试所有 API 端点:
curl https://app-<your-id>.azurewebsites.net/ curl https://app-<your-id>.azurewebsites.net/health curl https://app-<your-id>.azurewebsites.net/products curl https://app-<your-id>.azurewebsites.net/products/1
预期结果:所有端点返回有效的 JSON 且无错误
检查 Application Insights:
成功标准:所有 6-7 个资源存在,所有端点返回数据,实时指标显示活动。
目标:扩展 Flask 应用程序,添加一个新端点。
起始代码:src/web/app.py 中的当前端点
步骤:
编辑 src/web/app.py,在 get_product() 函数后添加一个新端点:
@app.route('/products/search/<keyword>') def search_products(keyword): """Search products by name or description.""" try: conn = get_db_connection() cursor = conn.cursor() cursor.execute( "SELECT id, name, description, price, created_at FROM products WHERE name LIKE ? OR description LIKE ?", (f'%{keyword}%', f'%{keyword}%') ) products = [] for row in cursor.fetchall(): products.append({ 'id': row[0], 'name': row[1], 'description': row[2], 'price': float(row[3]) if row[3] else None, 'created_at': row[4].isoformat() if row[4] else None }) cursor.close() conn.close() logger.info(f"Search for '{keyword}' returned {len(products)} results") return jsonify(products), 200 except Exception as e: logger.error(f"Error searching products: {str(e)}") return jsonify({'error': str(e)}), 500
部署更新后的应用程序:
azd deploy
测试新端点:
curl https://app-<your-id>.azurewebsites.net/products/search/laptop
预期结果:返回匹配“laptop”的产品
成功标准:新端点正常工作,返回过滤结果,并显示在 Application Insights 日志中。
目标:设置主动监控和警报。
步骤:
为 HTTP 500 错误创建警报:
# 获取应用程序洞察资源ID AI_ID=$(az monitor app-insights component show \ --app appi-<your-id> \ --resource-group rg-<env-name> \ --query id -o tsv) # 创建警报 az monitor metrics alert create \ --name "High-Error-Rate" \ --resource-group rg-<env-name> \ --scopes $AI_ID \ --condition "count requests/failed > 5" \ --window-size 5m \ --evaluation-frequency 1m \ --description "Alert when >5 failed requests in 5 minutes"
通过引发错误触发警报:
# 请求一个不存在的产品 for i in {1..10}; do curl https://app-<your-id>.azurewebsites.net/products/999; done
检查警报是否触发:
成功标准:警报规则已创建,错误触发警报,收到通知。
目标:添加一个新表并修改应用程序以使用它。
步骤:
通过 Azure 门户查询编辑器连接到 SQL 数据库
创建一个新的 categories 表:
CREATE TABLE categories ( id INT PRIMARY KEY IDENTITY(1,1), name NVARCHAR(50) NOT NULL, description NVARCHAR(200) ); INSERT INTO categories (name, description) VALUES ('Electronics', 'Electronic devices and accessories'), ('Office Supplies', 'Office equipment and supplies'); -- Add category to products table ALTER TABLE products ADD category_id INT; UPDATE products SET category_id = 1; -- Set all to Electronics
更新 src/web/app.py,在响应中包含类别信息
部署并测试
成功标准:新表存在,产品显示类别信息,应用程序仍然正常运行。
目标:添加 Azure Redis 缓存以提高性能。
步骤:
infra/main.bicep 中添加 Redis 缓存src/web/app.py 以缓存产品查询成功标准:Redis 已部署,缓存正常工作,响应时间提高 >50%。
提示:从 Azure Redis 缓存文档 开始。
为避免持续费用,完成后删除所有资源:
azd down
确认提示:
? Total resources to delete: 7, are you sure you want to continue? (y/N)
输入 y 以确认。
✓ 成功检查:
.azure/<env-name> 文件夹可删除替代方法(保留基础设施,删除数据):
# 仅删除资源组(保留 AZD 配置) az group delete --name rg-<env-name> --yes
AZD vs. ARM 模板:
AZD vs. Terraform:
AZD vs. Azure 门户:
将 AZD 想象为:Azure 的 Docker Compose——为复杂部署简化配置。
问:我可以使用其他编程语言吗?
答:可以!将 src/web/ 替换为 Node.js、C#、Go 或任何语言。相应更新 azure.yaml 和 Bicep。
问:如何添加更多数据库?
答:在 infra/main.bicep 中添加另一个 SQL 数据库模块,或使用 Azure 数据库服务中的 PostgreSQL/MySQL。
问:可以用于生产环境吗?
答:这是一个起点。用于生产时,请添加:托管身份、私有端点、冗余、备份策略、WAF 和增强监控。
问:如果我想使用容器而不是代码部署怎么办?
答:查看 容器应用示例,其中全程使用 Docker 容器。
问:如何从本地机器连接到数据库?
答:将您的 IP 添加到 SQL Server 防火墙:
az sql server firewall-rule create \ --resource-group rg-<env-name> \ --server sql-<unique-id> \ --name AllowMyIP \ --start-ip-address <your-ip> \ --end-ip-address <your-ip>
问:可以使用现有数据库而不是创建新数据库吗?
答:可以,修改 infra/main.bicep 以引用现有的 SQL Server,并更新连接字符串参数。
注意:此示例展示了使用 AZD 部署带数据库的 Web 应用的最佳实践。它包括工作代码、全面文档和实践练习以巩固学习。用于生产部署时,请根据您的组织需求审查安全性、扩展性、合规性和成本。
** 课程导航:**
免责声明:
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。原始语言的文档应被视为权威来源。对于关键信息,建议使用专业人工翻译。我们不对因使用此翻译而产生的任何误解或误读承担责任。