サマリ
- Alpine × Pythonの問題点については度々指摘されています🤔
- Using Alpine can make Python Docker builds 50× slower
- 軽量Dockerイメージに安易にAlpineを使うのはやめたほうがいいという話
- その原因のほとんどがAlpine同梱のCライブラリ「musl(マッスル)」に由来します
- ビルド時間が遅延したり、謎のバグを踏んだりします
- AlpineイメージのPythonを安易に導入した結果、その全ての問題をツモり悲しくなったので共有します👶
事象①:異常にビルド時間がかかる😨
起きたこと
Dockerイメージのビルドにメチャクチャ時間がかかりました。
ビルドのログを眺めていると、gRPC関連ライブラリ1のpip install
に30分程時間を要しているのが確認できました🤔
原因
前述したこちらの記事に答えがありました。
Using Alpine can make Python Docker builds 50× slower
Standard PyPI wheels don’t work on Alpine
簡単にまとめると、
- PyPIにはC拡張ライブラリのバイナリがホストされている(なので
pip install
で素早くインストール可能) - ただしこのバイナリはAlpine非対応のため使えない。Cコードをイチからコンパイルする必要アリ
ということです。
通常のライブラリならAlpineでも問題ないですが、C拡張ライブラリの場合は毎回一生懸命コンパイルすることになり、結果として鬼のようにビルド時間がかかってしまっていたわけです。
こちらの記事にも同様の説明がありました。
PyPIはLinux向けにはmanylinux1という形式でバイナリを提供しており、DebianでもRedHatでも高速にインストールできます。しかし、この形式はAlpineには対応していないため、C拡張を使うライブラリを使うと、Dockerイメージのビルド時間が伸びまくってしますわけです。
それでも、どうしても、PurePythonで処理速度はどうでも良い/お金がたくさんある、あるいはC拡張を使う場合でも人生を犠牲にしてでも、イメージサイズをどうしても減らしたいみたいな選ばれし者はAlpineを使う感じでしょうかね。
事象②:Segmentation Faultが起こる😨
起きたこと
AlpineイメージのPythonをCloud Runにデプロイし遊んでいたのですが、Uncaught signal: 11
なるエラーを吐きCloud Runくんが昇天することが多発しました。
Uncaught signal: 11
はSegmentation Faultを表しています。
余談ですが、厄介だったのは、ローカルでは再現しなかったことと、Cloud Run上でも数回に一度しか再現しなかったことです。
原因
muslのスレッドのスタックサイズに問題があったようです。
・muslはスレッドに対して極端に少ないスタックを割り当てる
(中略)
・Ruby・Python含む様々なプロジェクトがmuslのスタックオーバーフローに辛酸を舐めさせられている
スタックオーバーフローはセグフォの一因になり得ますのでこちらの影響を受けた可能性が高いです。
結論
余程のことがない限りPythonならAlpine以外を使用しましょう。
(補足ですが、使い方に依ればAlpineイメージでもPythonは問題なく動きます。全てを否定するわけではありません🙅♂️)
-
grpcio ↩