はじめに (対象読者・この記事でわかること)
この記事は、AWS Elastic Beanstalk(以下、EB)を使ってPythonアプリケーションをデプロイしている開発者の方、特にPython 3.4のような少し古い環境でNumPyなどの科学計算ライブラリを利用しようとしてコンパイルエラーに遭遇した方を対象にしています。
この記事を読むことで、Elastic BeanstalkのPython 3.4環境でNumPyインストール時に発生する具体的なコンパイルエラーの原因と、その一般的な解決策として「事前にビルドしたNumPyパッケージをアプリケーションに含めてデプロイする方法」がわかります。古い環境でのライブラリデプロイに関するトラブルシューティングの知識も深まるでしょう。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 * AWS Elastic Beanstalkの基本的な操作知識 * Pythonの基本的な知識とpipを用いたパッケージ管理の経験 * Linuxコマンドの基本的な知識 (特にSSH接続とログ確認) * 仮想環境 (virtualenv/venv) の利用経験
Elastic Beanstalk Python 3.4とNumPyインストールの課題
Elastic Beanstalkは、requirements.txtファイルに記載されたPythonパッケージをデプロイ時に自動的にインストールしてくれます。しかし、Python 3.4のような少し古い環境でNumPyのような数値計算ライブラリをインストールしようとすると、しばしばコンパイルエラーに直面することがあります。
NumPyは、高速な数値計算を実現するためにCやFortranなどのネイティブコードに依存しています。そのため、pip install numpyを実行する際には、これらのネイティブコードをコンパイルするためのコンパイラ(特にFortranコンパイラのgfortran)がシステムにインストールされている必要があります。
Python 3.4時代のElastic Beanstalk環境では、デフォルトでこれらのコンパイラが提供されていないか、バージョンが古いためにNumPyのコンパイルに失敗するケースが多発します。また、Python 3.4に対応するNumPyのバイナリホイール(事前にビルドされたパッケージ)がPyPI(Python Package Index)に存在しない、または最新のpipが古いPythonバージョン用の適切なホイールを解決できないといった問題も発生しやすくなります。これが、デプロイが失敗する主な原因となります。
Python 3.4環境でNumPyをデプロイするための具体的な手順
このセクションでは、Elastic BeanstalkのPython 3.4環境でNumPyのインストールエラーを回避し、アプリケーションにNumPyを組み込む具体的な手順を解説します。主要な解決策は、ローカル環境でNumPyをビルドまたは取得し、それをアプリケーションと一緒にバンドルしてデプロイする方法です。
ステップ1: ローカル環境の準備
まず、Elastic Beanstalk環境と可能な限り近い環境をローカルに用意します。これにより、EB上での問題を再現し、解決策を検証しやすくなります。
- Python 3.4のインストール:
Python 3.4がインストールされていない場合は、pyenvなどのバージョン管理ツールを使ってインストールします。
bash pyenv install 3.4.10 # または使用したいPython 3.4の特定のバージョン pyenv local 3.4.10 - 仮想環境の作成:
プロジェクトディレクトリ内でPython 3.4の仮想環境を作成し、アクティベートします。
bash python3.4 -m venv .venv_py34 source .venv_py34/bin/activate - 開発ツールのインストール:
NumPyのコンパイルに必要なシステムライブラリ(
gcc,gfortran,python-develなど)をローカル環境にインストールします。これは、あなたの開発環境のOSによって異なります。 例えば、Ubuntuであれば:bash sudo apt update sudo apt install build-essential gfortran python3.4-devCentOS/Amazon Linuxであれば:bash sudo yum update sudo yum install gcc gcc-gfortran python34-devel
ステップ2: ローカルでNumPyをインストールし、バンドルする
Elastic Beanstalk環境でコンパイルできないNumPyを、ローカルで事前にインストールし、デプロイパッケージに含めます。
-
NumPyのインストール: アクティベートした仮想環境内で、必要なバージョンのNumPyをインストールします。このとき、システムにコンパイラが適切にインストールされていれば、コンパイルが成功するはずです。
bash pip install numpy==1.11.3 # Python 3.4で安定動作するNumPyのバージョン例※ここで、もしgfortranが見つからないなどのエラーが出たら、ステップ1で開発ツールが正しくインストールされているか確認してください。 -
バンドル用のディレクトリ作成: アプリケーションのルートディレクトリに、NumPyやその他の外部ライブラリを格納するためのディレクトリ(例:
vendor)を作成します。bash mkdir vendor - NumPyパッケージのコピー:
仮想環境の
site-packagesディレクトリから、インストールしたNumPyパッケージをvendorディレクトリにコピーします。 仮想環境のsite-packagesのパスは、通常./.venv_py34/lib/python3.4/site-packages/のような場所になります。bash cp -r ./.venv_py34/lib/python3.4/site-packages/numpy vendor/ # もし依存関係もコピーするなら、まとめてコピーする cp -r ./.venv_py34/lib/python3.4/site-packages/*.whl vendor/ # バイナリホイールもあれば cp -r ./.venv_py34/lib/python3.4/site-packages/numpy-*.egg-info vendor/これで、アプリケーションのデプロイパッケージ(ZIPファイル)にvendor/numpyが含まれることになります。
ハマった点やエラー解決
Elastic Beanstalkでpip install numpyを実行すると、以下のようなエラーメッセージに遭遇することが一般的です。
エラーメッセージ例:
Running setup.py install for numpy ... error
Complete output from command /usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-0k1x8p6x/numpy/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-lkm2o6b2-record/install-record.txt --single-version-externally-managed --compile:
... (中略) ...
error: a setuptools-conda-test configuration error occurred: Failed to find Fortran compiler.
error: Command "gfortran -fno-strict-aliasing -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fno-strict-aliasing -I/usr/include/python3.4m -c numpy/linalg/lapack_lite/python_xerbla.c -o build/temp.linux-x86_64-3.4/numpy/linalg/lapack_lite/python_xerbla.o" failed with exit status 1
----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-0k1x8p6x/numpy/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-lkm2o6b2-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-0k1x8p6x/numpy/
原因:
このエラーは、NumPyのコンパイルに必要なFortranコンパイラ(gfortran)がElastic Beanstalk環境にインストールされていないために発生しています。特にPython 3.4の環境では、このような開発ツールがデフォルトで不足していることが頻繁にあります。また、Python 3.4に対応するNumPyのバイナリホイールがない場合、pipはソースコードからのビルドを試みるため、この問題が顕在化します。
解決策
ローカルでNumPyをバンドルし、Elastic Beanstalk環境がそのNumPyモジュールを正しく認識できるようにパスを設定します。
-
requirements.txtからNumPyを削除: アプリケーションのrequirements.txtファイルからnumpyの行を削除します。これにより、EBがNumPyのインストールを試みなくなり、コンパイルエラーを回避できます。 -
アプリケーションコードでのパス設定: アプリケーションのエントリポイントとなるPythonファイル(例:
application.pyやwsgi.py)の冒頭で、バンドルしたNumPyのパスをPythonの検索パスに追加します。 ```python import sys import osアプリケーションルートからの相対パスでvendorディレクトリを追加
EBのデフォルトでは/opt/python/current/appがアプリケーションのルート
sys.path.insert(0, os.path.join(os.path.dirname(file), 'vendor'))
または直接パスを指定
sys.path.insert(0, '/opt/python/current/app/vendor')
import numpy # これでnumpyがインポートできるようになる
``os.path.dirname(file)は現在のファイルのディレクトリを指します。アプリケーションのルートがカレントディレクトリになるようにデプロイされていれば、この方法で./vendor`を指定できます。 -
.ebextensionsでの永続的なパス設定 (推奨): もしアプリケーションコードを修正したくない場合や、より恒久的な解決策を求める場合は、.ebextensionsを使ってElastic Beanstalk環境のPYTHONPATHを設定することができます。アプリケーションのルートに.ebextensionsディレクトリを作成し、その中に.configファイル(例:01_add_pythonpath.config)を配置します。```yaml
.ebextensions/01_add_pythonpath.config
files: "/etc/profile.d/pythonpath_vendor.sh": mode: "000755" owner: root group: root content: | #!/bin/bash # Elastic Beanstalkのアプリケーションルートは通常 /opt/python/current/app export PYTHONPATH=$PYTHONPATH:/opt/python/current/app/vendor echo "PYTHONPATH added: /opt/python/current/app/vendor" >> /var/log/cfn-init.log
container_commands: 01_add_path: command: "sh /etc/profile.d/pythonpath_vendor.sh" leader_only: true
`` この設定により、デプロイ時に/etc/profile.d/にスクリプトが配置され、以降のシェルセッションやアプリケーション実行時にPYTHONPATHに/opt/python/current/app/vendorが追加されます。これにより、アプリケーションコード内でsys.pathを直接操作することなく、import numpy`が可能になります。 -
アプリケーションのデプロイ:
vendorディレクトリ、変更後のrequirements.txt、.ebextensions(利用する場合)、およびアプリケーションコードをすべて含んだZIPファイルを作成し、Elastic Beanstalkにデプロイします。
この手順により、Elastic BeanstalkがNumPyをコンパイルする手間を省き、ローカルで事前に準備したNumPyモジュールを利用してアプリケーションを正常に動作させることができます。
まとめ
本記事では、Elastic BeanstalkのPython 3.4環境でNumPyのインストールがコンパイルエラーで失敗する問題に対する解決策として、ローカルでNumPyをインストール・バンドルし、デプロイパッケージに含める方法を解説しました。
- 古い環境の課題: Python 3.4のような古いEB環境では、NumPyのコンパイルに必要なシステムライブラリ(特に
gfortran)がデフォルトで不足しており、pip installが失敗する。 - ローカルでの事前準備:
requirements.txtに頼らず、ローカル環境でNumPyをインストールし、そのパッケージをvendorディレクトリなどに入れてアプリケーションにバンドルする。 - 実行パスの設定: バンドルしたNumPyをPythonが認識できるように、アプリケーションコードで
sys.pathを操作するか、.ebextensionsを用いてPYTHONPATHを設定する。
この記事を通して、古いElastic Beanstalk環境でもNumPyのような複雑なライブラリを安定してデプロイできるようになり、一般的なデプロイエラーのトラブルシューティングスキルが向上したことでしょう。 今後は、より新しいPython環境でのデプロイのベストプラクティスや、Dockerを用いたデプロイ方法についても記事にする予定です。
参考資料
