How to install matplotlib on Alpine

Question:

Trying to install matplotlib on an alpine docker image. I get a bunch of ugly messages. Am I missing some additional pre-req that needs to be manually installed?

Here is docker file:

    FROM openjdk:8-jre-alpine
    RUN apk update
    RUN apk add --no-cache tesseract-ocr
    RUN echo     import numpy, matplotlib, skimage, _tkinter > test.py
    RUN apk add --no-cache python3
    RUN pip3 install --upgrade pip setuptools
    RUN apk add --no-cache py3-numpy
    RUN pip install matplotlib

And the relevant docker output (similar output if I just do it live on Linux)

Collecting kiwisolver>=1.0.1
 Downloading kiwisolver-1.3.1.tar.gz (53 kB)
   ERROR: Command errored out with exit status 1:
    command: /usr/bin/python3.6 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-yp9mr2j7/kiwisolver_29f6c98e09ef4d15af4bbadde3b1c2a2/setup.py'"'"'; __file__='"'"'/tmp/pip-install-yp9mr2j7/kiwisolver_29f6c98e09ef4d15af4bbadde3b1c2a2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'rn'"'"', '"'"'n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-t2cdn0ra
        cwd: /tmp/pip-install-yp9mr2j7/kiwisolver_29f6c98e09ef4d15af4bbadde3b1c2a2/
   Complete output (44 lines):
   WARNING: The wheel package is not available.
     ERROR: Command errored out with exit status 1:
      command: /usr/bin/python3.6 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-wheel-nil1gs35/cppy_c6bc34a322e5441da8a1a97ba7950d95/setup.py'"'"'; __file__='"'"'/tmp/pip-wheel-nil1gs35/cppy_c6bc34a322e5441da8a1a97ba7950d95/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'rn'"'"', '"'"'n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-wb4xn65c
          cwd: /tmp/pip-wheel-nil1gs35/cppy_c6bc34a322e5441da8a1a97ba7950d95/
     Complete output (6 lines):
     usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
        or: setup.py --help [cmd1 cmd2 ...]
        or: setup.py --help-commands
        or: setup.py cmd --help
   
     error: invalid command 'bdist_wheel'
     ----------------------------------------
     ERROR: Failed building wheel for cppy
   ERROR: Failed to build one or more wheels
   Traceback (most recent call last):
     File "/usr/lib/python3.6/site-packages/setuptools/installer.py", line 126, in fetch_build_egg
       subprocess.check_call(cmd)
     File "/usr/lib/python3.6/subprocess.py", line 311, in check_call
       raise CalledProcessError(retcode, cmd)
   subprocess.CalledProcessError: Command '['/usr/bin/python3.6', '-m', 'pip', '--disable-pip-version-check', 'wheel', '--no-deps', '-w', '/tmp/tmpa3b9n_qa', '--quiet', 'cppy>=1.1.0']' returned non-zero exit status 1.
   
   The above exception was the direct cause of the following exception:
   
   Traceback (most recent call last):
     File "<string>", line 1, in <module>
     File "/tmp/pip-install-yp9mr2j7/kiwisolver_29f6c98e09ef4d15af4bbadde3b1c2a2/setup.py", line 92, in <module>
       cmdclass={'build_ext': BuildExt},
     File "/usr/lib/python3.6/site-packages/setuptools/__init__.py", line 152, in setup
       _install_setup_requires(attrs)
     File "/usr/lib/python3.6/site-packages/setuptools/__init__.py", line 147, in _install_setup_requires
       dist.fetch_build_eggs(dist.setup_requires)
     File "/usr/lib/python3.6/site-packages/setuptools/dist.py", line 676, in fetch_build_eggs
       replace_conflicting=True,
     File "/usr/lib/python3.6/site-packages/pkg_resources/__init__.py", line 766, in resolve
       replace_conflicting=replace_conflicting
     File "/usr/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1049, in best_match
       return self.obtain(req, installer)
     File "/usr/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1061, in obtain
       return installer(requirement)
     File "/usr/lib/python3.6/site-packages/setuptools/dist.py", line 732, in fetch_build_egg
       return fetch_build_egg(self, req)
     File "/usr/lib/python3.6/site-packages/setuptools/installer.py", line 128, in fetch_build_egg
       raise DistutilsError(str(e)) from e
   distutils.errors.DistutilsError: Command '['/usr/bin/python3.6', '-m', 'pip', '--disable-pip-version-check', 'wheel', '--no-deps', '-w', '/tmp/tmpa3b9n_qa', '--quiet', 'cppy>=1.1.0']' returned non-zero exit status 1.
   ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
Error response from daemon: The command '/bin/sh -c pip3 install matplotlib' returned a non-zero code: 1
Asked By: Peter Kronenberg

||

Answers:

Since I spent some time on it and since matplotlib is a dependency used for development, I still decided to push that as an answer integrating good practice pointed out by @β.εηοιτ.βε

As reported in my comments, you are missing quite a few dependencies to install matploblib from pip which will build on the go.

Here is a Dockerfile that will install matplotlib in a single image layer, kept as thin as possible by removing the build dependencies in the last step

FROM openjdk:8-jre-alpine

RUN apk add --no-cache tesseract-ocr python3 py3-numpy && 
    pip3 install --upgrade pip setuptools wheel && 
    apk add --no-cache --virtual .build-deps gcc g++ zlib-dev make python3-dev py-numpy-dev jpeg-dev && 
    pip3 install matplotlib && 
    apk del .build-deps
Answered By: Zeitounator

After a long time searching and trying, Zeitounator’s answer is NOT working under python:3.9-alpine, throwing exceptions as below:
required by py-numpy-dev

And inspired by James Endicott’s answer, to solve this case, you need to add more requirements packages:

apk --no-cache add musl-dev linux-headers g++

Combining their two conclusions:

pip install --upgrade pip setuptools wheel
apk add --no-cache --virtual .build-deps musl-dev linux-headers g++ gcc zlib-dev make python3-dev jpeg-dev
pip install matplotlib
apk del .build-deps

BTW, if NOT NECESSARY, using pyhon3:ubuntu is a much smartter choise.
It takes too long time to build

Answered By: ChowRex

I finally made matplotlib work under Alpine.
I trigger the these two commands after Docker have started, from within Python

import os
os.system('''apk add g++ jpeg-dev zlib-dev libjpeg make''')
os.system("pip3 install matplotlib")

This takes 2-3min to build for me. To speed up the deploy time, I have added a manuell trigger to build it (don’t need the matplotlib all the time)

Answered By: Punnerud