Docker: Installing python cryptography on alpine linux distribution

11,042

Solution 1

Alpine is a headache distro for most Python packages that ship C/C++ extensions (code written in C/C++ that is compiled to a shared object and loaded in Python via a foreign function library). The reason for that is that is PEP 513 which portability definition between Linux distros, manylinux1, is based on glibc/glibcxx. Since Alpine uses musl libc, no manylinux1 compatible wheel can be installed on Alpine. So when you issue pip install cryptography, the wheel with the compiled extensions is filtered and pip tries to build the package with all the C extensions from source.

installing with the system package manager

This is the preferred way and was mentioned by @GracefulRestart in the comments; use it if you don't need the bleeding edge version of the package. Install it with apk:

$ apk add py-cryptography

installing with pip

Should you need the bleeding edge version, you can try building it from source by installing with pip.

Preparing the build environment

You will need the compiler and libraries with header files: musl, OpenSSL, libffi and Python itself:

$ apk add gcc musl-dev libffi-dev openssl-dev python3-dev


Building

$ pip install pkgname

hides the build log by default. To see the complete build log, add -vvv to increase verbosity. (Optional) Also, you can explicitly prohibit installing manylinux1 wheels by adding -

-no-binary=pkgname

so the build from source will be enforced.

$ pip install cryptography -vvv --no-binary=cryptography

Solution 2

My fix was downgrading to alpine3.6 (I ran into this issue when I was using alpine3.8).

FROM python:3.6.6-alpine3.6
RUN apk update && apk add libressl-dev postgresql-dev libffi-dev gcc musl-dev python3-dev 

Solution 3

Found a fix. Specifying an older version of libressl-dev has fixed my DockerHub build.

apk add --no-cache libressl-dev=2.6.4-r2

2.7.3-rx is currently the latest version of libressl-dev and is the problematic version. Try using the version mentioned above in your Dockerfile to see if it works for you.

Share:
11,042
Marko Zadravec
Author by

Marko Zadravec

Updated on July 01, 2022

Comments

  • Marko Zadravec
    Marko Zadravec 3 months

    I am a little bit new to Docker and deployment cycle.

    I have Django application that we would like to deploy with uWSGI to docker container. Actually the deploy worked perfectly for a few weeks, but now it soundly report error...

    Error seam to be with cryptography package:

    build/temp.linux-x86_64-3.6/_openssl.c:52862:10: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion]
    build/temp.linux-x86_64-3.6/_openssl.c: In function '_cffi_f_SSL_set_options':
    build/temp.linux-x86_64-3.6/_openssl.c:52895:14: warning: conversion to 'long int' from 'long unsigned int' may change the sign of the result [-Wsign-conversion]
       { result = SSL_set_options(x0, x1); }
                  ^~~~~~~~~~~~~~~
    build/temp.linux-x86_64-3.6/_openssl.c:52895:14: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion]
    error: command 'gcc' failed with exit status 1
    ----------------------------------------
    Command "/usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-dg_tg9pa/cryptography/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-my98rwq4/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-dg_tg9pa/cryptography/ 
    The command '/bin/sh -c pip install --no-cache-dir -r requirements.txt' returned a non-zero code: 1
    ERROR: Job failed: exit code 1
    

    Our docker file looks like

    FROM python:3-alpine
    ENV PYTHONUNBUFFERED 1
    WORKDIR /usr/src/app
    RUN apk add --no-cache gcc mailcap python3-dev build-base linux-headers pcre-dev postgresql-dev libffi-dev libressl-dev
    COPY requirements.txt ./
    RUN pip install --no-cache-dir -r requirements.txt
    

    As I mention the docker file and requirement.txt hasn't change between success build and failed one. (What is the most strange to me...)

    The only think I could think is that command

    FROM python:3-alpine
    

    is taking the different version of alpine...

    Is this possible? What could be wrong? How to fix it?