You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker+FastAPI+SQLAlchemy连接MSSQL遇Unicode转换失败求助

解决Docker+FastAPI+SQLAlchemy连接MSSQL的Unicode转换失败问题

问题背景

在Alpine Linux镜像构建的Docker环境中,使用FastAPI+SQLAlchemy+pyodbc连接采用Japanese_CI_AS排序规则的MSSQL数据库时,触发以下错误:

sqlalchemy.exc.DBAPIError: (pyodbc.Error) ('HY000', '[HY000] [Microsoft][ODBC Driver 18 for SQL Server]Unicode conversion failed (22) (SQLGetData)')

已尝试禁用pyodbc连接池(pyodbc.pooling = False)但无效;添加ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so后错误消失,但数据库查询无返回结果。

环境配置

Dockerfile

FROM python:3.12.3-alpine
WORKDIR /app
COPY requirements.txt .

RUN apk update
RUN apk add gcc libc-dev g++ libffi-dev libxml2 unixodbc-dev
RUN apk add bash curl gnupg
RUN apk add gnu-libiconv gnu-libiconv-dev

#Download the desired package(s)
RUN curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/msodbcsql18_18.3.3.1-1_amd64.apk
RUN curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/mssql-tools18_18.3.1.1-1_amd64.apk

#(Optional) Verify signature, if 'gpg' is missing install it using 'apk add gnupg':
RUN curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/msodbcsql18_18.3.3.1-1_amd64.sig
RUN curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/mssql-tools18_18.3.1.1-1_amd64.sig

RUN curl https://packages.microsoft.com/keys/microsoft.asc  | gpg --import -
RUN gpg --verify msodbcsql18_18.3.3.1-1_amd64.sig msodbcsql18_18.3.3.1-1_amd64.apk
RUN gpg --verify mssql-tools18_18.3.1.1-1_amd64.sig mssql-tools18_18.3.1.1-1_amd64.apk

#Install the package(s)
RUN apk add --allow-untrusted msodbcsql18_18.3.3.1-1_amd64.apk
RUN apk add --allow-untrusted mssql-tools18_18.3.1.1-1_amd64.apk

ENV GLIBC_VER=2.35-r1
RUN apk update --no-cache && \
    apk add --no-cache git curl binutils && \
    curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub && \
    curl -sLO "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk" && \
    curl -sLO "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk" && \
    apk add --force-overwrite --no-cache glibc-${GLIBC_VER}.apk glibc-bin-${GLIBC_VER}.apk && \
    rm -rf /var/cache/apk/*

RUN pip install -r requirements.txt

ENV PYTHONPATH=./fast-api

COPY . .
EXPOSE 5002

requirements.txt

fastapi==0.110.1
uvicorn==0.29.0
SQLAlchemy==2.0.29
pandas==2.2.2
pyodbc==5.1.0
email-validator==2.1.1

database.py

import sqlalchemy as sa
from sqlalchemy import create_engine
import pyodbc
pyodbc.pooling = False

SQLALCHEMY_DATABASE_URL = sa.engine.url.URL(
    "mssql+pyodbc",
    username="user",
    password="pass",
    host="hostname",
    port=1433,
    database="test",
    query={
        "driver": "ODBC Driver 18 for SQL Server",
        "TrustServerCertificate": "yes",
    },
)
print(SQLALCHEMY_DATABASE_URL)

engine = create_engine(
    SQLALCHEMY_DATABASE_URL
    , pool_recycle=1500
    )

解决方案

1. 调整iconv预加载与字符集配置

Alpine的gnu-libiconv处理日文Unicode转换时需明确指定字符集,修改Dockerfile:

# 替换原有LD_PRELOAD配置,添加字符集环境变量
ENV LD_PRELOAD=/usr/lib/preloadable_libiconv.so
ENV LC_ALL=ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8

# 在安装glibc后添加日文语言包安装步骤
RUN apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "Asia/Tokyo" > /etc/timezone && \
    apk add --no-cache locale && \
    echo "ja_JP.UTF-8 UTF-8" >> /etc/locale.gen && \
    locale-gen ja_JP.UTF-8

2. 修改数据库连接字符串

在database.py的连接参数中添加字符集指定:

SQLALCHEMY_DATABASE_URL = sa.engine.url.URL(
    "mssql+pyodbc",
    username="user",
    password="pass",
    host="hostname",
    port=1433,
    database="test",
    query={
        "driver": "ODBC Driver 18 for SQL Server",
        "TrustServerCertificate": "yes",
        "charset": "utf8"
    },
)

3. 强制pyodbc的Unicode编码规则

在database.py开头添加编码设置:

import pyodbc
# 禁用连接池
pyodbc.pooling = False
# 强制指定Unicode编码
pyodbc.setencoding(encoding='utf-8')
pyodbc.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
pyodbc.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')

4. 切换至Debian基础镜像(备选方案)

若Alpine的iconv兼容性问题难以彻底解决,可改用Debian镜像规避:

FROM python:3.12.3-slim-bookworm
WORKDIR /app
COPY requirements.txt .

# 安装MS ODBC驱动依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl gnupg2 unixodbc-dev gcc g++ \
    && curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
    && curl https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list \
    && apt-get update && ACCEPT_EULA=Y apt-get install -y msodbcsql18 mssql-tools18 \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

RUN pip install -r requirements.txt

ENV PYTHONPATH=./fast-api

COPY . .
EXPOSE 5002

验证方法

启动容器后执行测试查询:

from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

db = SessionLocal()
# 查询含日文字符的记录
result = db.execute(sa.text("SELECT * FROM your_table WHERE id = 1")).fetchone()
print(result)
db.close()

若能正常打印含日文字符的结果,说明问题已解决。

内容的提问来源于stack exchange,提问作者tsushimaru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 13:19:55