LoginSignup
1
0

Cloud Run + PipenvでPATHエラーが出てハマった話

Last updated at Posted at 2024-01-22

概要

Cloud Runを試そうと思い、Pipenvで作ったサンプルアプリのDockerイメージをデプロイしたところ、以下のエラーが出て起動しませんでした。

Error: the command XXX could not be found within PATH.
※ XXXは対象のコマンド

image.png

画像はCloud Loggingのログです。今回は uvicorn を使用していました。

このエラーを解消したお話です。

要約

Dockerfileに以下を追加して解消しました。
PIPENV_VENV_IN_PROJECT は、pipenvの仮想環境をプロジェクトのディレクトリに作成するための環境変数です。

ENV PIPENV_VENV_IN_PROJECT=1

ローカルとCloud Runでコンテナの実行ユーザーが異なり、パスが合わなかったことが原因と考えられます。

環境

  • Python 3.10.13
  • pipenv, version 2023.10.24
  • alpine3.19

詳細

エラー原因

Pipenvは、デフォルトだとプロジェクト外の場所に仮想環境を作成します。
ビルドしたときのログをみると、/root 配下に環境を作成していることがわかります。

✔ Successfully created virtual environment!
Virtualenv location: /root/.local/share/virtualenvs/app-4PlAip0Q

元々のDockerfileは以下です。プロジェクトは /app 配下です。

FROM python:3.10.13-alpine3.19

WORKDIR /app

COPY Pipfile Pipfile.lock app/ /app/
RUN pip install pipenv && pipenv sync

EXPOSE 80

ENTRYPOINT ["pipenv", "run", "serve"]

このイメージをCloud Runにデプロイすると、先のエラーが出力されます。

ここでCloud Loggingのログを見ると、仮想環境の場所として/home配下のディレクトリが参照されていることがわかります。

Virtualenv location: /home/.local/share/virtualenvs/app-4PlAip0Q

image.png

エラーの直接原因は、PATHの違いにより作成された仮想環境を参照していないためと想定されます。

なぜPATHが違うのか

Cloud Runでのコンテナ実行ユーザーが非rootユーザーであるため、と考えられます。

ローカルではあまり意識しないかもしれませんが、コンテナのベストプラクティスとしてrootユーザーでのコンテナ実行は推奨されていません。これはOWASPの Kubernetes Top 10 で確認できます。

Application processes should not run as root: Running the process inside of a container as the root user is a common misconfiguration in many clusters. While root may be an absolute requirement for some workloads, it should be avoided when possible. If the container were to be compromised, the attacker would have root-level privileges that allow actions such as starting a malicious process that otherwise wouldn’t be permitted with other users on the system.


(Google 翻訳) アプリケーションプロセスは root として実行しないでください。コンテナ内でプロセスを root ユーザーとして実行することは、多くのクラスターでよくある構成ミスです。一部のワークロードでは root が絶対必要な場合がありますが、可能な場合は避ける必要があります。コンテナが侵害された場合、攻撃者は root レベルの権限を持ち、システム上の他のユーザーには許可されない悪意のあるプロセスの開始などのアクションを許可することになります。

Cloud Run は Google Cloud が管理する Borg (KubernetesのベースになったGoogle社内ツール) 上でコンテナが稼働するサービスです。このプラクティスと同様に、Cloud Runも非rootユーザーで実行されているのだと考えられます。

非rootユーザーでは /root 配下に作られた仮想環境は参照できず、PATHのエラーとなります。試しに、Dockerfile に非rootユーザーを追加してdocker build & docker run すると、同じエラーが再現できます。

FROM python:3.10.13-alpine3.19

WORKDIR /app

COPY Pipfile Pipfile.lock app/ /app/
RUN pip install pipenv && pipenv sync

+ RUN adduser -D appuser -h /home/appuser && \
+     chown -R appuser:appuser /app /home/appuser
+ USER appuser

EXPOSE 80

ENTRYPOINT ["pipenv", "run", "serve"]
  • docker run の実行結果
✔ Successfully created virtual environment!
Virtualenv location: /home/appuser/.local/share/virtualenvs/app-4PlAip0Q
Error: the command uvicorn (from serve) could not be found within PATH.

解決方法

以下の通り、PIPENV_VENV_IN_PROJECT の環境変数を設定します。
これにより、プロジェクト配下の /app/.venv に仮想環境が作成され、非rootユーザーにもPATHが通ります。

FROM python:3.10.13-alpine3.19

WORKDIR /app

# pipenvの仮想環境をプロジェクトに作成
+ ENV PIPENV_VENV_IN_PROJECT=1

COPY Pipfile Pipfile.lock app/ /app/
RUN pip install pipenv && pipenv sync

EXPOSE 80

ENTRYPOINT ["pipenv", "run", "serve"]

参考

  • Github の issue

  • pipenv 公式ドキュメント

  • Cloud Run を徹底解説! - G-gen Tech Blog

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0