👀

Azure Functions公式Pythonベースイメージで pip install したCLIが見つからない理由と対処法

に公開

Azure Functionsでコンテナデプロイを行う際に、Microsoft公式が提供しているPythonベースイメージを利用しています。

このベースイメージを利用したコンテナイメージを作成時に、詰まったポイントについてまとめます。

詰まったポイント

以下のMicrosoft公式が提供しているPythonイメージをベースイメージとして利用し、pipでuvをインストールした際に問題が起こりました。

※ uv を例にしていますが、pip install した他のライブラリのCLIでも同じです

https://mcr.microsoft.com/en-us/artifact/mar/azure-functions/python/tags

以下のようなDockerfileを用意してビルドしたところ、最後のRUNで「uv: command not found」のエラーが出たのです。エラーの通り、uv の実行ファイルが配置されているディレクトリに PATH が通っていない状態ですね。

FROM mcr.microsoft.com/azure-functions/python:4-python3.14

...(中略)

RUN pip install uv

...(中略)

RUN uv ○○

(そもそもuvをpipで入れなければいいでしょって話は今回置いといてください。)

今回は uv をインストールしようとしていますが、「pipで入れた何らかのライブラリのCLIコマンドをたたく」というシチュエーションはほかにもあるかもなので、今回はあくまでuvを例に説明します。

uv公式が推奨しているインストール方法はこちらです

一方、ベースイメージにDocker公式のPython slim系を使った場合は、問題なく処理が通ります(パスが通っています)。

FROM python:3.14-slim

...(中略)

RUN pip install uv

...(中略)

RUN uv ○○

https://hub.docker.com/_/python

この挙動の差分が気になったので、調べてみました。

原因:pip install で配置されるコンソールスクリプト(実行ファイル)に PATH が通っていない

はい。原因は見出しの通りになります。ベースイメージとしてAzure FunctionsのPython用公式イメージを使った場合、pip install uv を実行すると、uv の実行ファイルが /opt/python/{該当バージョン}/bin/ に配置されます(この辺りの詳細は原因調査の章へ)。こちらにはパスが通っていないのでuv コマンドはそのままでは実行できません

一方で、Docker公式が提供しているPython slimイメージに関しては、pip install uv時の実行ファイルが /usr/local/bin/ に配置されます。/usr/local/bin/にはパスが通っているので、後続の処理で uv コマンドが問題なく実行可能です。

対策:python -m を付けてuvのコマンド実行するか、/opt/python/3/bin/にパスを通す

原因は上記の通りですので、簡単な対策としては2点かと。
(※そもそもpipを使ってuvを入れない!というのがありますが、置いといて...)

  1. pip installで入れたライブラリのCLIコマンドは python -m を付けて実行する
  2. pip installで実行ファイルがインストールされる /opt/python/3/bin/ にパスを通す

まずは1つ目から。

pip install uv まで実行されたイメージを用意してインタラクティブモードで立ち上げ・接続します。この状態で以下のコマンドをじっこうすると...。

root@d8daf34b07c3:/# uv --version
bash: uv: command not found
root@d8daf34b07c3:/# python -m uv --version
uv 0.9.21

python -m uv は、PATH 上の実行ファイルを探索するのではなく、Python の import パス上にある uv モジュールの __main__ を直接実行します。このため、パスが通っていない場所に実行ファイルがなくても、Pythonが参照できる位置にあれば問題なく実行できます。

次に2つ目。

これは単純で、パスを通してしまえばいいという話です。

Dockerfile内に ENV PATH=/opt/python/3/bin:${PATH} を追加すればOKです。

FROM mcr.microsoft.com/azure-functions/python:4-python3.14

ENV PATH=/opt/python/3/bin:${PATH}

※ここで/opt/python/{該当バージョン}/bin/にパスを通すのではなく、/opt/python/3/bin/としている点については、原因究明の章のステップ4を見てもらえると。

基本的には python -m uv のように python -m を付けて実行する方法の方がオススメかなと思います。

この方法であれば、実行ファイルがどのディレクトリに配置されているかや、ベースイメージごとの PATH 設定やインストール先の差異に影響されにくく、再利用性の高い Dockerfile を書くことができます。

この辺りは、用途に応じて使い分けるのが良いのかな~と思っています。

(繰り返しになりますが、uv に関してはそもそも pip install せず、uv 公式で紹介されているインストール方法を採用するのが良いかと。)

おまけ:原因調査

原因と対策は上記の通りなので、こちらは原因を見つけるまでの流れを簡単に。

まじめに公式のベースイメージのDockerfileを追えばわかるのかもしれませんが、今回はインタラクティブモードで愚直に追ってみました。

調査の流れ

  1. 各ベースイメージをインタラクティブモードで実行する
  2. pip -V でpip自体のインストール先を見る
  3. pip install uv してみてライブラリの保存位置を確認する
  4. pip のパスを確認する

1. 各ベースイメージをインタラクティブモードで実行する

Microsoft公式のAzure FunctionsのPython用イメージと、Docker公式が出しているPythonのslimイメージをインタラクティブモードで起動します。

起動コマンドはそれぞれ以下の通りです

# Azure Functions
docker run -it --rm --entrypoint /bin/bash mcr.microsoft.com/azure-functions/python:4-python3.14
# Python slim
docker run -it --rm --entrypoint /bin/bash python:3.14-slim

2. pip -V でpip自体のインストール先を見る

pip -Vを実行すると、そのpipのバージョンとインストール先が見えます。

まずは、Azure Functions用から。

root@13d98e8caadd:/# pip -V
pip 25.2 from /opt/python/3.14.0rc2/lib/python3.14/site-packages/pip (python 3.14)

/opt/python/3.14.0rc2/ 配下に入ってますね。この pip を使ってインストールされたライブラリは、基本的にこの配下に配置されます。(実行ファイルは/opt/python/3.14.0rc2/bin/ 配下に)

一方で、Python slimイメージでは

root@10232723a4e1:/# pip -V
pip 25.3 from /usr/local/lib/python3.14/site-packages/pip (python 3.14)

/usr/local/ 配下にpipがあることがわかるかと思います。

3. pip install uv してみてライブラリの保存位置を確認する

次に pip install uv をしてみて、実際にどこに保存されているのか確認します。

まずは、Azure Functions用から。

root@13d98e8caadd:/# pip install uv 
root@13d98e8caadd:/# pip show uv
Name: uv
Version: 0.9.21
Summary: An extremely fast Python package and project manager, written in Rust.
Home-page: https://pypi.org/project/uv/
Author: 
Author-email: "Astral Software Inc." <hey@astral.sh>
License: 
Location: /opt/python/3.14.0rc2/lib/python3.14/site-packages
Requires: 
Required-by:

予想通り、/opt/python/3.14.0rc2/ 配下に入っていることがわかるかと思います。

Python slimイメージでは…

root@10232723a4e1:/# pip install uv 
root@10232723a4e1:/# pip show uv
Name: uv
Version: 0.9.21
Summary: An extremely fast Python package and project manager, written in Rust.
Home-page: https://pypi.org/project/uv/
Author: 
Author-email: "Astral Software Inc." <hey@astral.sh>
License: 
Location: /usr/local/lib/python3.14/site-packages
Requires: 
Required-by: 

こちらも予想通り、/usr/local/ 配下に入っていることがわかるかと思います。

4. pip のパスを確認する

ここで、気になるのがそもそも今使っている pip コマンドはどこのパス経由で使っているのか、です。気になるので確認してみます。

Azure Functions用の場合

root@13d98e8caadd:/# type -a pip
pip is /usr/bin/pip
pip is /bin/pip

どうやらpipコマンドを実行すると /usr/bin/pip を見に行っているみたいです。ls -l で実態を見てみます。

root@13d98e8caadd:/# ls -l /usr/bin/pip
lrwxrwxrwx 1 root root 21 Dec 31 05:05 /usr/bin/pip -> /opt/python/3/bin/pip

よくみると、どうやら /usr/bin/pip はシンボリックリンクのようですね。nameiコマンドで、もう少し見てみます。

root@13d98e8caadd:/# namei /usr/bin/pip
f: /usr/bin/pip
 d /
 d usr
 d bin
 l pip -> /opt/python/3/bin/pip
   d /
   d opt
   d python
   l 3 -> 3.14.0rc2
     d 3.14.0rc2
   d bin
   - pip

namei の出力はシンボリックリンクのつながりを示しています。このことからわかるのは...

  • /usr/bin/pip/opt/python/3/bin/pip を指すシンボリックリンク。
  • /opt/python/3 はさらに /opt/python/3.14.0rc2 を指すシンボリックリンク。

結果として、pipコマンド実行時の最終実体は /opt/python/3.14.0rc2/bin/pip (実ファイル)ということがわかります。

よって、pip install uv とすると /opt/python/3.14.0rc2/bin/ 配下に uv の実行ファイルが設置されるというわけですね。

そして、環境変数にはこの部分のパスが通っていないのでエラーとなるわけです

root@13d98e8caadd:/# echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

このため、対策の1つとして環境変数に「/opt/python/3/bin/ のパスを通す」というのが入ったというわけです。(/opt/python/3.14.0rc2/bin/ だとわかりにくいので、ラップしてくれている /opt/python/3/bin/ を指すようにしました。)

一方でPython slimの方を見てみると…

root@10232723a4e1:/# namei /usr/local/bin/pip
f: /usr/local/bin/pip
 d /
 d usr
 d local
 d bin
 l pip -> pip3
   - pip3

見ての通り、pipは /usr/local/ 配下にあるので、実行ファイルは /usr/local/bin/ 配下に設置されます。ここのパスは問題なく通っているので、特に何もせずとも uv コマンドが実行できるということですね。

まとめ

今回は、Azure Functionsのコンテナデプロイ用イメージを作成する際に、Microsoft公式が提供するPythonイメージを使ったときに詰まった点についてまとめました。

どなたかの参考になれば幸いです🙋‍♂️

参考

https://zenn.dev/yamaday/articles/azure-functions-python-project

Discussion