通过Azure容器部署的FastAPI在Azure App Service无法读取MySQL数据
问题分析与排查修复步骤
核心问题定位
从Docker日志的Can't open lib 'ODBC Driver 18 for SQL Server'错误,结合你提到的“本地已安装ODBC驱动可正常连接”,核心问题是Docker容器内未正确安装对应ODBC驱动,同时存在两个潜在的关键错误:
一、优先确认:数据库类型与驱动匹配
你开头提到是“Azure上MySQL数据库”,但连接代码使用的是ODBC Driver 18 for SQL Server(SQL Server专用驱动),这是完全不匹配的:
- 若使用Azure MySQL:需改用MySQL专用驱动,比如
mysql-connector-python(无需ODBC),或pyodbc配合MySQL ODBC 8.0 Driver - 若实际使用Azure SQL Server:驱动选择正确,但容器内安装步骤有误
二、针对Azure SQL Server的Docker驱动安装修复
如果确实是Azure SQL Server,按以下步骤修正Dockerfile:
1. 正确的驱动安装步骤(以Debian/Ubuntu基础镜像为例)
使用python:x-slim作为基础镜像时,需安装微软官方的ODBC驱动18,完整Dockerfile示例:
FROM python:3.11-slim # 安装系统依赖与SQL Server ODBC驱动 RUN apt-get update && apt-get install -y --no-install-recommends \ unixodbc \ unixodbc-dev \ curl \ gnupg2 \ && curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \ && curl https://packages.microsoft.com/config/debian/11/prod.list > /etc/apt/sources.list.d/mssql-release.list \ && apt-get update \ && ACCEPT_EULA=Y apt-get install -y msodbcsql18 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # 设置工作目录与依赖安装 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir fastapi uvicorn pyodbc COPY . . # 启动FastAPI服务 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
2. 验证容器内驱动是否安装成功
运行容器后,进入容器执行以下命令确认驱动存在:
# 查看已注册的ODBC驱动 odbcinst -j # 检查驱动文件是否存在 ls /opt/mssql-tools/lib64/libmsodbcsql-18.so
3. 修正连接代码的驱动名称
Linux环境下ODBC驱动名称无需大括号,修改db.py:
driver= "ODBC Driver 18 for SQL Server" # 去掉大括号
三、针对Azure MySQL的修复方案
如果确实是Azure MySQL,建议改用更简单的mysql-connector-python(无需ODBC):
1. 修改依赖与连接代码
- 在
requirements.txt中添加mysql-connector-python - 替换
db.py的连接逻辑:
import mysql.connector from mysql.connector import Error server = 'xxx.mysql.database.azure.com' # Azure MySQL的服务器地址格式 database = 'mydatabase' username = 'xxxxxx' password = 'xxxxxx' def conn(): try: connection = mysql.connector.connect( host=server, database=database, user=username, password=password, ssl_disabled=False # Azure MySQL要求SSL ) return connection except Error as e: print(f"数据库连接错误: {e}") raise
2. 修改API接口的查询逻辑
同样使用参数化查询避免SQL注入:
@app.get('/id/{id}') async def op(id:int): conn = conn() cursor = conn.cursor() cursor.execute("SELECT * FROM inventory WHERE id = %s", (id,)) result = cursor.fetchone() cursor.close() conn.close() if not result: return {"error": "未找到对应记录"} return {"id": result[0], "name": result[1], "q": result[2]}
四、关键安全修复:避免SQL注入
你当前使用f"select * from dbo.inventory where id = {id}"拼接SQL语句,存在严重的SQL注入风险,必须改用参数化查询(上述示例已修正),这不仅是安全要求,也能避免特殊字符导致的SQL语法错误。
五、Azure App Service部署额外检查
- 确认App Service的启动命令与Dockerfile的CMD一致,比如使用
uvicorn main:app --host 0.0.0.0 --port 80 - 在App Service的“日志流”中查看详细错误日志,确认驱动问题是否已解决
- 确认数据库防火墙允许App Service的出站IP访问(虽然你说无限制,但可再次验证)
内容的提问来源于stack exchange,提问作者Alex Raj Kaliamoorthy
相关产品推荐
相关产品推荐

