解决Django部署时xmlsec报错:lxml与libxml2版本不匹配
Django部署python3-saml时lxml与xmlsec的libxml2版本不匹配问题
问题详情
部署Django 4.1后端时,需安装依赖lxml和xmlsec的python3-saml,编写的精简Dockerfile如下:
FROM python:3.10.6 # Install necessary packages RUN apt-get update && \ apt-get install -y s3fs pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl libxmlsec1 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # set work directory WORKDIR /usr/src/app # install dependencies RUN pip install --upgrade pip COPY ./requirements.txt . RUN pip install -r requirements.txt RUN pip install python3-saml && \ pip install --force-reinstall --no-binary lxml lxml # copy project COPY . . # create cache directory RUN mkdir -p /var/tmp/django_cache ENTRYPOINT ["./docker-entrypoint.sh"]
镜像构建无异常,但部署时触发如下错误:
File "/usr/local/lib/python3.10/site-packages/onelogin/saml2/auth.py", line 12, in <module> import xmlsec xmlsec.Error: (100, 'lxml & xmlsec libxml2 library version mismatch')
尝试指定lxml 4.6.3、4.9.3版本重新编译安装均无效,pip安装python3-saml时默认会安装lxml 5.2.2。当前requirements.txt内容如下:
apipkg==1.5 asgiref==3.7.2 asn1crypto==1.4.0 astroid==2.4.2 async-timeout==4.0.3 attrs==20.1.0 authy==2.2.6 autopep8==1.5.4 certifi==2020.6.20 cffi==1.15.1 chardet==3.0.4 click==7.1.2 colorama==0.4.6 coverage==5.2.1 cryptography==42.0.2 Cython==0.29.21 decorator==5.1.1 defusedxml==0.7.1 deprecation==2.1.0 dictor==0.1.11 Django==4.1 django-cors-headers==3.5.0 django-debug-toolbar==4.3.0 django-eav2==0.13.0 django-filter==2.4.0 django-liststyle==0.1 django-redis==5.4.0 django-redis-cache==3.0.1 django-rest-auth==0.9.5 django-reversion==5.0.3 django-simple-history==2.11.0 djangorestframework==3.14.0 djangorestframework-jwt==1.11.0 djangorestframework-simplejwt==5.2.2 drf-extensions==0.7.1 elementpath==4.2.1 exceptiongroup==1.2.0 execnet==1.7.1 factory-boy==3.0.1 Faker==4.1.2 flake8==3.8.3 future==0.18.2 idna==2.10 importlib-metadata==1.7.0 inflection==0.5.1 iniconfig==1.0.1 install==1.3.5 isodate==0.6.1 isort==5.5.3 Jinja2==2.11.2 lazy-object-proxy==1.4.3 MarkupSafe==1.1.1 mccabe==0.6.1 more-itertools==8.5.0 numpy==1.23.5 packaging==20.4 pandas==1.4.1 Paste==3.7.1 phonenumbers==8.12.16 pikepdf==7.2.0 Pillow==9.5.0 pluggy==0.13.1 psycopg2==2.9.3 psycopg2-binary==2.9.3 py==1.9.0 pycodestyle==2.6.0 pycparser==2.20 pycryptodomex==3.20.0 pyflakes==2.2.0 Pygments==2.6.1 PyJWT==1.7.1 pylint==2.6.0 pymemcache==4.0.0 PyMuPDF==1.22.3 pyOpenSSL==24.0.0 pyparsing==2.4.7 PyPDF2==1.26.0 pytest==7.1.3 pytest-cov==2.10.1 pytest-django==3.9.0 python-dateutil==2.8.1 python-memcached==1.59 pytz==2020.1 PyYAML==5.3.1 qrcode==7.3.1 redis==3.5.3 redispy==3.0.0 repoze.who==3.0.0 requests==2.24.0 six==1.15.0 slack-sdk==3.12.0 sqlparse==0.3.1 text-unidecode==1.3 toml==0.10.1 tomli==2.0.1 typing_extensions==4.9.0 tzdata==2023.4 urllib3==1.25.10 wcwidth==0.2.5 WebOb==1.8.7 Werkzeug==1.0.1 wrapt==1.12.1 xmlschema==2.5.1 zipp==3.1.0 zope.interface==6.1
解决方案
问题核心是系统级libxml2库与lxml编译依赖的libxml2版本不匹配,解决步骤如下:
1. 确认系统libxml2版本
先在Docker容器内执行命令,查看系统安装的libxml2版本:
dpkg -s libxml2 | grep Version
以python:3.10.6镜像(基于Debian Bullseye)为例,得到的版本通常是2.9.10+dfsg-6.7+deb11u1。
2. 安装匹配版本的lxml
lxml 5.x系列依赖更高版本的libxml2(2.9.12+),而Debian Bullseye的系统libxml2是2.9.10,因此需要选择lxml 4.9.x系列(比如4.9.4),该系列与libxml2 2.9.10完全兼容。
修改Dockerfile中的安装命令,确保重新编译安装匹配版本的lxml:
RUN pip install python3-saml && \ pip install --force-reinstall --no-binary :all: lxml==4.9.4
--no-binary :all:参数强制pip从源码编译lxml,确保它链接到系统安装的libxml2库。
3. 优化安装顺序(可选)
为避免其他依赖包覆盖lxml版本,可将lxml指定版本添加到requirements.txt末尾:
# requirements.txt末尾添加 lxml==4.9.4
然后Dockerfile中调整为:
RUN pip install --upgrade pip COPY ./requirements.txt . RUN pip install -r requirements.txt RUN pip install python3-saml && \ pip install --force-reinstall --no-binary :all: lxml==4.9.4
4. 验证版本匹配
容器启动后,执行Python代码确认版本一致:
import lxml.etree import xmlsec print(lxml.etree.LIBXML_VERSION) print(xmlsec.LIBXML2_VERSION)
输出的两个版本号必须完全相同,问题即可解决。
内容的提问来源于stack exchange,提问作者Philippe
相关产品推荐
相关产品推荐

