grpc: Unable to run grpcio wheel on alpine arvm7
What version of gRPC and what language are you using?
1.41.0
in python. Any grpcio release over 1.31.0 exhibits a variation on the problem.
What operating system (Linux, Windows,…) and version?
Linux arm32v7/alpine:3.12
What runtime / compiler are you using (e.g. python version or version of gcc)
Python 3.8.10
though other versions also show the same problem
What did you do?
Given an example Dockerfile
like this:
FROM arm32v7/alpine:3.12
RUN apk add --no-cache python3 py3-pip
RUN apk add libstdc++ libc6-compat
RUN python3 --version
WORKDIR /code
COPY requirements.txt .
COPY example.py .
RUN pip3 install --no-cache-dir --only-binary=grpcio -r requirements.txt
CMD python3 ./example.py
Note that this also has problems finding the shared library without libstdc++
and libc6-compat
but the errors has changed across grpc versions.
requirements.txt
:
grpcio==1.41.0
google-cloud-pubsub
example.py
#!/usr/bin/python
from google.cloud import pubsub_v1
def main():
print("Hello world")
if __name__ == "__main__":
main()
Then run a build like this:
$ docker build --tag grpcio-armv7 .
What did you expect to see?
$ docker run grpcio-armv7
Hello world
Note, that this is what I see for alpine images on other architectures or different armv7 images like this:
FROM arm32v7/python:3.8-buster
What did you see instead?
$ docker run grpcio-armv7
Traceback (most recent call last):
File "./example.py", line 3, in <module>
from google.cloud import pubsub_v1
File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/__init__.py", li
ne 17, in <module>
from google.cloud.pubsub_v1 import types
File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/types.py", line
25, in <module>
from google.api_core import gapic_v1
File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/__init__.py",
line 16, in <module>
from google.api_core.gapic_v1 import config
File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/config.py", line 23, in <module>
import grpc
File "/usr/lib/python3.8/site-packages/grpc/__init__.py", line 22, in <module>
from grpc import _compression
File "/usr/lib/python3.8/site-packages/grpc/_compression.py", line 15, in <module>
from grpc._cython import cygrpc
ImportError: Error relocating /usr/lib/python3.8/site-packages/grpc/_cython/cygrpc.cpython-38-arm-linux-gnueabihf.so: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7reserveEv: symbol not found
When using an older version of grpcio
such as 1.38.X, I see an error message like:
Traceback (most recent call last):
File "./example.py", line 3, in <module>
from google.cloud import pubsub_v1
File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/__init__.py", line 17, in <module>
from google.cloud.pubsub_v1 import types
File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/types.py", line 25, in <module>
from google.api_core import gapic_v1
File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/__init__.py", line 16, in <module>
from google.api_core.gapic_v1 import config
File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/config.py", line 23, in <module>
import grpc
File "/usr/lib/python3.8/site-packages/grpc/__init__.py", line 23, in <module>
from grpc._cython import cygrpc as _cygrpc
ImportError: Error relocating /usr/lib/python3.8/site-packages/grpc/_cython/cygrpc.cpython-38-arm-linux-gnueabihf.so: __strftime_l: symbol not found
This is similar to the first post of https://github.com/grpc/grpc/issues/24808 where the armv7 binary wheel has problems with alpine.
Anything else we should know about your project / environment?
This seems to have been an armv7
plus alpine
issue that first happened last year. I have some history in https://github.com/home-assistant/core/issues/56669 though this was first seen with https://github.com/home-assistant/core/issues/40266 and https://github.com/home-assistant/core/issues/40148
Also note above that the Dockerfile
explicitly adds libstdc++ libc6-compat
which are not necessary for other platforms besides arvm7
. Ideally that should not be needed and this could run on musl directly.
The discussion in https://github.com/grpc/grpc/issues/26620 seems quite relevant. Is building musllinux wheels for armv7 the right solution?
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 3
- Comments: 26 (8 by maintainers)
@lidizheng
Just came across this issue with grpcio on armhf on a musl based distro (alpine).
The root issue seems to be that grpc is publishing a vanilla wheel (non-manylinux or musllinux) for armhf on pypi, which is only meant for glibc based systems, but because it is not container based and is vanilla, thus named
grpcio-1.43.0-cp39-cp39-linux_armv7l.whl
, pip cannot really tell whether it is compatible with the musl based system or not. It happily installs it, but the installed package does not work. Therefore anyone doingpip install grpcio
on an alpine armhf system will have a broken package.The x86_64 and aarch64 versions are fine, because they are actually published as
manylinux
on pypi, which is properly recognized by pip as not compatible with a musl based system and therefore pip correctly compiles from source.I think the proper solution would be for grpc to not publish a vanilla wheel like that on pypi, and only rely on manylinux and musllinux (container based) wheels on linux (no idea how it is on other platforms like windows).
I’m not aware of any other project on pypi that publishes vanilla wheels.
Thanks
PS. If you build these wheels via
pip wheel
on armhf on ubuntu (glibc) and alpine (musl), both systems will produce wheels namedgrpcio-1.43.0-cp39-cp39-linux_armv7l.whl
and pip cannot distinguish between the two, but they won’t be compatible with each other. That’s why it’s best for official wheels on pypi to be container based as pip is aware of their compatibility and doesn’t incorrectly use them on the wrong system.We, at linuxserver.io, publish various vanilla wheels in our repos for reuse in our docker images, but in order to overcome the above mentioned issue, we keep glibc and musl based wheels in separate endpoints: https://wheel-index.linuxserver.io/ To complicate matters further, vanilla wheels also suffer from incompatibility due to system dependency package versions. For instance
alpine 3.14
and3.15
both have python 3.9 so pip thinks their vanilla wheels are compatible, butcffi
for instance uses a shared library oflibffi
. If thecffi
wheel is built onalpine 3.14
, it is linked tolibffi 7
, but when it’s used on alpine 3.15, it fails because3.15
containslibffi 8
. We can get away with maintaining separate repos for glibc vs musl, and different distro versions, because we can define different repos in our docker images, however for publishing on pypi, which is a single universal repo, the solution is to ship container based wheels with proper compatibility and with statically linked deps.EDIT2: I should clarify that my above comments apply to cpython wheels. Pure python wheels (*-pyX-none-any.whl) are not glibc or musl dependent so they can be published as is on pypi with no issues.
I was able to get an armv7 alpine wheel built for home assistant (codified here https://github.com/allenporter/wheels-grpc)
However, that wheel doesn’t work on a plain Alpine install either and fails with the same error as the wheel built from grpc source. I think the hole assistant is building python from source and may be patching it in some way.
However my immediate user need is solved for the moment and we’ve been able to move to the latest grpc for the next release.
More investigation is needed here for a grpc built wheel that works on Alpine armv7
OK – I had problems finding audithweel for the musl architecture and had to disable it, so that makes sense. However, i’m having the
cygrpc
problem on both architectures so perhaps i’ll focus there first.This is the same problem in https://github.com/grpc/grpc/issues/26094 so I included a repro case there.
Issue also happening running through Bazel on Apple M1.