初投稿です.今後よろしくお願いします.
ある研究案件でRaspberry PI上のPythonのslimコンテナ(執筆時python:3.9-slim)にpip経由で色々入れようとしたところいろいろ躓いたのでメモ
Debianのaptで入るrustが古かったり,Dockerfile内でのPATH変数の更新などで一苦労しました
最後に書きますが,今のところこの方法じゃない方がよいかもです.
2023.02.02追記
Arm32v7環境のみです.Arm64v8環境では特に問題なくpipによるインストールが通ります
前提条件
OS: Rasbian( on Raspberrypi4 )Docker及びDocker-composeをapt経由でインストール
Dockerfile内にpip経由でbcryptを含むいくつか(主にFlask関係)をインストールする文を書いた
ベースコンテナはpython:3.9-slim
経緯
面倒な方は結論だけどうぞ出てきたエラー
From: python:3.9-slim
.....
RUN pip install bcrypt....
とbcryptパッケージのpipインストールを含むコンテナ(例えばdocker-composeやFlask-bcryptなど)を構築しようとすると
error: can't find Rust compiler
でbcryptパッケージのインストールがこけます
Rustのコンパイラが見つからないようです
対策1
apt-get install rustc を追加結果
This package requires Rust >=1.56.0.
執筆時点でのPython:slimコンテナのベースはDebian(Bullseye),apt経由で入るrustは1.42
古いのが入ってしまいました
対策2
本家の情報を元にインストールシェルをcurlで落として来て実行.なお,本家シェルファイルはInteractiveな形式なので本家のInstructionにある
RUN curl https://sh.rustup.rs -sSf | sh
ではなく
RUN curl https://sh.rustup.rs -sSf > /rust.sh && sh /rust.sh -y
としています.そのままshに投げると躓きます.
なお,slimコンテナではgccパッケージもomitされてるので事前にapt-get gccしないとコケます.
結果2
error: can't find Rust compiler<br/>
入れたはずのrustが見つかりません
どうやらPATHが通ってない様子
そもそも本家インストールシェルの最後にsource $HOME/.cargo/env を実行しろと出るくらいなのでPATHはいじってくれない様子
Dockerfileはsh環境で実行されるので愚直にsource..とやるとアウトです
sourceの代わりに . $HOME/.cargo/envとやりますが...コケます
その代わりに直打ちでPATHに追加してみました
対策3
Dockderfileに以下のrustcへのPATHを追加RUN PATH=$PATH:/root/.cargo/bin
結果3
何故かまた見つかりません.ここで調べたら以下の記事を発見
Updating PATH Environment Variable in Dockerfile
Dockerfile開発中はRUN構文を小分けにすることもあるかと思いますが
(少なくとも自分はそうして,ある程度固まってからまとめてます)
RUN構文でPATH変数を更新しても恒久的には変わらないのだそうです.
ということで
最終対策
pip installと同じRUN文にPATH追加分を合わせて書きますRUN PATH=$PATH:/root/.cargo/bin && pip install .....
ようやく通りました.
参考記事では
ENV PATH=$PATH:<追加PATH>
する方法もあるよ,と書いています
(個人的にはコンポーネント入ってからPATHいじるものだろという固定概念があったので目から鱗でした)
そもそも
途中で開発環境入れたりするせいか,slimコンテナの恩恵であるサイズがむしろ通常コンテナをベースにした時より大きくなってます.(注:まだチューニングしてないため今後改善する可能性あり)
(投稿後4時間後追記)コンテナの仕様も大分固まったので一つのRUN文でrustcの導入,bcryptのインストール,rustc他開発環境の削除までやってみました.
結果だらだらRUN文を並べていたころに比べイメージの容量が6分の1になりました
また詳しい方ならapt-get install python3-bcrypt とかでいけんじゃね?と思われるかと思いますが,今のところ自分の環境では
apt経由で入れたパッケージがpip経由のpythonパッケージから見つけららず,別途調査中です ( 追加記事参照ください )
rustとか入れなくていいようにbcrypt関係だけaptで入れてみたところ,pipで入れたflaskから見つからないのでPATHを通す必要がありました
結論
Dockerfile内でのPATH変数の挙動が分かっただけでもいっか
Pythonのslimタグが付いたコンテナだとbcryptパッケージのインストールに失敗するので
Dockerfile内に
RUN apc-get install gcc
した上で
RUN curl https://sh.rustup.rs -sSf > /rust.sh && sh /rust.sh -y
でRustの最新コンパイラを入れて,
RUN PATH=$PATH:/root/.cargo/bin && pip install ....
とすると通ります
但しコンパイラのコンパイルからやるので1時間近くかかります..