Dockerのalpine上 Flask-Askをpipでインストールしようとするとエラー

はじめに

年末にEcho dotを購入したので、Alexaのカスタムスキルを作ろうと思いました。

Alexaのカスタムスキルは以前作成したことがあったのでその際に使用したFlask_Askを使って作成しようと思い取り掛かりました。

ところがFlask_Askはしばらくメンテナンスされていないようで、pipでインストールする際にエラーが出てしまったのでその対処を備忘としてまとめます。

pip installでエラー

今回はDocker上に環境を作っており、Python3.7.2-alpine3.8のDockerimageを使用しました。

Docker Hub

早速開発しようとFlask_Askをpipでインストールしようとしたらエラーになりました。

$ pip install flask_ask
Collecting flask_ask
  Using cached https://files.pythonhosted.org/packages/6a/f5/d4709ae94584a0b1541e9b52b2d25a8a1bdb6e2da9d6870f23fdd0523a30/Flask-Ask-0.9.8.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-la1z83pq/flask-ask/setup.py", line 8, in <module>
        from pip.req import parse_requirements
    ModuleNotFoundError: No module named 'pip.req'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-la1z83pq/flask-ask/

'pip.req'が無いと言われています。
いろいろ調べてみると既知のエラーらしく、コミュニティでも話題になっていました。
どうやらsetup.pyを編集すれば解消するようです。

stackoverflow.com

pip downloadでダウンロードしてからオフラインでインストール

setup.pyを編集するためには、まずはソースをダウンロードしなくてはなりません。

qiita.com

こちらを参考に以下の手順で実施しました。

まずはsrcディレクトリを作成し、そこにパッケージをダウンロードします。

$ mkdir src
$ pip download -d src --no-binary :all: flask_ask
Collecting flask_ask
  Downloading https://files.pythonhosted.org/packages/6a/f5/d4709ae94584a0b1541e9b52b2d25a8a1bdb6e2da9d6870f23fdd0523a30/Flask-Ask-0.9.8.tar.gz (40kB)
    100% |████████████████████████████████| 40kB 2.8MB/s
  Saved ./src/Flask-Ask-0.9.8.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-download-on3tlt2h/flask-ask/setup.py", line 8, in <module>
        from pip.req import parse_requirements
    ModuleNotFoundError: No module named 'pip.req'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-download-on3tlt2h/flask-ask/

$ ls -l src/
total 40
-rw-r--r--    1 root     root         40142 Jan  8 07:03 Flask-Ask-0.9.8.tar.gz

何やらまたsetup.pyでエラーが出ていますが、ちゃんとダウンロード出来ているようです。

setup.pyの編集

ダウンロードしたtar.gzファイルを解凍し、setup.pyを編集します。

$ cd src/
$ tar -zxvf Flask-Ask-0.9.8.tar.gz
$ ls -l
total 40
drwxr-xr-x   15 501      wheel          480 Jan  8 07:05 Flask-Ask-0.9.8
-rw-r--r--    1 root     root         40142 Jan  8 07:03 Flask-Ask-0.9.8.tar.gz
$ cd Flask-Ask-0.9.8
$ vim setup.py

setup.pyを以下のように編集します。

"""
Flask-Ask
-------------

Easy Alexa Skills Kit integration for Flask
"""
from setuptools import setup
# from pip.req import parse_requirements
try: # for pip >= 10
    from pip._internal.req import parse_requirements
except ImportError: # for pip <= 9.0.3
    from pip.req import parse_requirements

setup(
    name='Flask-Ask',
    version='0.9.8',
    url='https://github.com/johnwheeler/flask-ask',
    license='Apache 2.0',
    author='John Wheeler',
    author_email='john@johnwheeler.org',
    description='Rapid Alexa Skills Kit Development for Amazon Echo Devices in Python',
    long_description=__doc__,
    packages=['flask_ask'],
    zip_safe=False,
    include_package_data=True,
    platforms='any',
    install_requires=[
        str(item.req) for item in
        parse_requirements('requirements.txt', session=False)
    ],
    test_requires=[
        'mock',
        'requests'
    ],
    test_suite='tests',
    classifiers=[
        'License :: OSI Approved :: Apache Software License',
        'Framework :: Flask',
        'Programming Language :: Python',
        'Environment :: Web Environment',
        'Intended Audience :: Developers',
        'Operating System :: OS Independent',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
        'Topic :: Software Development :: Libraries :: Python Modules'
    ]
)

setup.pyを編集したパッケージフォルダを再度tarで固めます。

$ mv Flask-Ask-0.9.8.tar.gz Flask-Ask-0.9.8_bk.tar.gz
$ tar -zcvf Flask-Ask-0.9.8.tar.gz Flask-Ask-0.9.8
$ ls -l
total 80
drwxr-xr-x   15 501      wheel          480 Jan  8 07:06 Flask-Ask-0.9.8
-rw-r--r--    1 root     root         40284 Jan  8 07:08 Flask-Ask-0.9.8.tar.gz
-rw-r--r--    1 root     root         40142 Jan  8 07:03 Flask-Ask-0.9.8_bk.tar.gz

alpineにgccのインストール

pipでインストールを実行したところ、何やら別のエラーが出ました。

$ pip install Flask-Ask-0.9.8.tar.gz
Processing ./Flask-Ask-0.9.8.tar.gz
Collecting aniso8601==1.2.0 (from Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/5b/fb/251a0dd2f4710e60664ddd8bd3485bd8362530f47af9e88f4061fe589ebf/aniso8601-1.2.0.tar.gz (59kB)
    100% |████████████████████████████████| 61kB 2.2MB/s
Collecting Flask==0.12.1 (from Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/f4/43/fb2d5fb1d10e1d0402dd57836cf9a78b7f69c8b5f76a04b6e6113d0d7c5a/Flask-0.12.1-py2.py3-none-any.whl (82kB)
    100% |████████████████████████████████| 92kB 5.1MB/s
Collecting pyOpenSSL==17.0.0 (from Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/8c/b7/0048adbf09ad93f571e70fb3100e696d4711cdcbfe38161690d716a5ed35/pyOpenSSL-17.0.0-py2.py3-none-any.whl (51kB)
    100% |████████████████████████████████| 61kB 3.1MB/s
Collecting PyYAML==3.12 (from Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/4a/85/db5a2df477072b2902b0eb892feb37d88ac635d36245a72a6a69b23b383a/PyYAML-3.12.tar.gz (253kB)
    100% |████████████████████████████████| 256kB 7.0MB/s
Collecting six==1.11.0 (from Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl
Collecting python-dateutil (from aniso8601==1.2.0->Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/74/68/d87d9b36af36f44254a8d512cbfc48369103a3b9e474be9bdfe536abfc45/python_dateutil-2.7.5-py2.py3-none-any.whl (225kB)
    100% |████████████████████████████████| 235kB 5.4MB/s
Requirement already satisfied: click>=2.0 in /usr/local/lib/python3.7/site-packages (from Flask==0.12.1->Flask-Ask==0.9.8) (7.0)
Requirement already satisfied: Jinja2>=2.4 in /usr/local/lib/python3.7/site-packages (from Flask==0.12.1->Flask-Ask==0.9.8) (2.10)
Requirement already satisfied: itsdangerous>=0.21 in /usr/local/lib/python3.7/site-packages (from Flask==0.12.1->Flask-Ask==0.9.8) (1.1.0)
Requirement already satisfied: Werkzeug>=0.7 in /usr/local/lib/python3.7/site-packages (from Flask==0.12.1->Flask-Ask==0.9.8) (0.14.1)
Collecting cryptography>=1.7 (from pyOpenSSL==17.0.0->Flask-Ask==0.9.8)
  Downloading https://files.pythonhosted.org/packages/f3/39/d3904df7c56f8654691c4ae1bdb270c1c9220d6da79bd3b1fbad91afd0e1/cryptography-2.4.2.tar.gz (468kB)
    100% |████████████████████████████████| 471kB 6.3MB/s
  Installing build dependencies ... error
  Complete output from command /usr/local/bin/python -m pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-x0_m8e40 --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- setuptools>=18.5 wheel "cffi>=1.7,!=1.11.3; python_implementation != 'PyPy'":
  Collecting setuptools>=18.5
    Downloading https://files.pythonhosted.org/packages/37/06/754589caf971b0d2d48f151c2586f62902d93dc908e2fd9b9b9f6aa3c9dd/setuptools-40.6.3-py2.py3-none-any.whl (573kB)
  Collecting wheel
    Downloading https://files.pythonhosted.org/packages/ff/47/1dfa4795e24fd6f93d5d58602dd716c3f101cfd5a77cd9acbe519b44a0a9/wheel-0.32.3-py2.py3-none-any.whl
  Collecting cffi!=1.11.3,>=1.7
    Downloading https://files.pythonhosted.org/packages/e7/a7/4cd50e57cc6f436f1cc3a7e8fa700ff9b8b4d471620629074913e3735fb2/cffi-1.11.5.tar.gz (438kB)
      Complete output from command python setup.py egg_info:

          No working compiler found, or bogus compiler options passed to
          the compiler from Python's standard "distutils" module.  See
          the error messages above.  Likely, the problem is not related
          to CFFI but generic to the setup.py of any Python package that
          tries to compile C code.  (Hints: on OS/X 10.8, for errors about
          -mno-fused-madd see http://stackoverflow.com/questions/22313407/
          Otherwise, see https://wiki.python.org/moin/CompLangPython or
          the IRC channel #python on irc.freenode.net.)

      ----------------------------------------
  Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-zydf2ff8/cffi/

  ----------------------------------------
Command "/usr/local/bin/python -m pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-x0_m8e40 --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- setuptools>=18.5 wheel "cffi>=1.7,!=1.11.3; python_implementation != 'PyPy'"" failed with error code 1 in None

コンパイラが見つからないよーというエラーが出ています。
調べると対処方法が見つかりました。

ja.stackoverflow.com

alpineにgccが含まれていない事が原因のようです。

早速alpine上でパッケージをインストールしてから再試行しますと、また別のエラーが、、、

$ apk add build-base libffi-dev
$ pip install Flask-Ask-0.9.8.tar.gz

〜〜〜〜略〜〜〜〜
  build/temp.linux-x86_64-3.7/_openssl.c:498:30: fatal error: openssl/opensslv.h: No such file or directory
   #include <openssl/opensslv.h>
                                ^
  compilation terminated.
  error: command 'gcc' failed with exit status 1

  ----------------------------------------
  Failed building wheel for cryptography
〜〜〜〜略〜〜〜〜
    build/temp.linux-x86_64-3.7/_openssl.c:498:30: fatal error: openssl/opensslv.h: No such file or directory
     #include <openssl/opensslv.h>
                                  ^
    compilation terminated.
    error: command 'gcc' failed with exit status 1

    ----------------------------------------
Command "/usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-z1_hjgoi/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-rfu9q4ne/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-z1_hjgoi/cryptography/

今度はopensslが無い!と怒られてしまっています。インストールしてから再度pipでインストール実行します。

$ apk add openssl-dev
$ pip install Flask-Ask-0.9.8.tar.gz
〜〜〜〜略〜〜〜〜
Successfully built Flask-Ask cryptography
Installing collected packages: cryptography, pyOpenSSL, PyYAML, Flask-Ask
Successfully installed Flask-Ask-0.9.8 PyYAML-3.12 cryptography-2.4.2 pyOpenSSL-17.0.0

無事インストール出来ました。

$ python
Python 3.7.1 (default, Dec 21 2018, 03:21:42)
[GCC 6.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from flask_ask import Ask, statement, question, session
>>>
>>>

ちゃんとimportも出来るようになりました。
これでFlask_Askを使用できるようになったので、これからカスタムスキルを開発していきたいと思います。