はじめに
Cloud Run のビルドが python 1.14 以降は pip から uv に変わるという話を聞いて、uv を使った Clound Run 関数 (Cloud Run Functions) の構築をメモします。
-
Python アプリケーションをビルドする#パッケージ マネージャー
https://docs.cloud.google.com/docs/buildpacks/python?hl=ja#package-manager -
Cloud Run リリースノート 2025-12-19
https://docs.cloud.google.com/run/docs/release-notes#December_19_2025
(2026年3月時点ではプレビューっぽい?)
ディレクトリ構成
今回のプロジェクトディレクトリは以下を想定します。hello プロジェクトとして、app 配下に開発コード、terraform 配下に IaC コード、.dist がデプロイ資材になります。app ディレクトリ下で、uv init と uv venv を実行しました。キャッシュフォルダなどを記載しているのは、今後の説明で必要になるためです。
hello
├── .dist/
├── app/
│ ├── .pytest_cache/
│ ├── .venv/
│ ├── src/
│ │ ├── __pycache__/
│ │ └── main.py
│ ├── tests/
│ ├── .python-version
│ ├── pyproject.toml
│ ├── pytest.ini
│ ├── README.md
│ └── uv.lock
└── terraform/
pyproject.toml
実行パッケージとして functions-framework をインストールし、開発パッケージとして、pytest をインストールしてあります。環境別に requirements.txt を分けなくて良いだけでスッキリします。
[project]
name = "app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.14"
dependencies = [
"functions-framework>=3.10.1",
]
[dependency-groups]
dev = [
"pytest>=9.0.2",
]
terraform(Cloud Run 関数のデプロイ部分)
幾つか悩んだところがあったので記載します。
- requirements.txt 同様、pyproject.toml をルートディレクトリに含まないといけないので、app フォルダを丸々デプロイする
- 実行環境から除外したいファイルもあるので、
archive_fileのexcludesパラメータで個別に指定 - エントリポイント関数のファイルがルートに無いため、GOOGLE_FUNCTION_SOURCE で指定する必要がある
locals {
app_path = "(app フォルダへの相対パス)"
}
# 実行サービスアカウント
resource "google_service_account" "sa_functions_hello" {
account_id = "sa-func-hello"
description = "for cloud function python14 hello test"
}
# IAM
resource "google_project_iam_member" "iam_sa_functions_hello" {
for_each = toset([
"roles/run.invoker",
])
project = "(プロジェクト名)"
role = each.key
member = "serviceAccount:${google_service_account.sa_functions_hello.email}"
}
# デプロイコードアーカイブ
data "archive_file" "functions_zip" {
type = "zip"
source_dir = local.app_path
output_path = "${local.app_path}/../.dist/app.zip"
excludes = [
".*/**",
"**/__pycache__",
"tests",
"pytest.ini",
"README.md",
]
}
# デプロイコードの GCS 格納先
resource "google_storage_bucket_object" "functions_gcsobj_zip" {
name = "hello/${data.archive_file.functions_zip.output_md5}.zip"
bucket = "(コード格納バケット)"
source = "${local.app_path}/../.dist/app.zip"
depends_on = [
data.archive_file.functions_zip
]
}
# Functions 本体
resource "google_cloudfunctions2_function" "functions" {
name = "hello-test"
description = "hello-test"
location = "(関数ロケーション)"
project = "(プロジェクト名)"
build_config {
runtime = "python314"
entry_point = "function_main"
source {
storage_source {
bucket = "(コード格納バケット)"
object = google_storage_bucket_object.functions_gcsobj_zip.name
}
}
environment_variables = {
GOOGLE_FUNCTION_SOURCE = "src/main.py"
}
}
service_config {
service_account_email = google_service_account.sa_functions_hello.email
}
depends_on = [
google_storage_bucket_object.functions_gcsobj_zip,
google_service_account.sa_functions_hello
]
}
デプロイ結果
Cloud Run のビルドも通って、確かにデプロイされました。さらば requirements.txt、こんにちは uv.lock!
おわりに
pip とも互換のある uv が採用されるのはうれしいので、この方向で uv をメインに使っても良いかなと思います。
