1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

uv を使って Cloud Run 関数開発 (+terraform)

1
Last updated at Posted at 2026-04-01

はじめに

Cloud Run のビルドが python 1.14 以降は pip から uv に変わるという話を聞いて、uv を使った Clound Run 関数 (Cloud Run Functions) の構築をメモします。

(2026年3月時点ではプレビューっぽい?)

ディレクトリ構成

今回のプロジェクトディレクトリは以下を想定します。hello プロジェクトとして、app 配下に開発コード、terraform 配下に IaC コード、.dist がデプロイ資材になります。app ディレクトリ下で、uv inituv 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 関数のデプロイ部分)

幾つか悩んだところがあったので記載します。

  1. requirements.txt 同様、pyproject.toml をルートディレクトリに含まないといけないので、app フォルダを丸々デプロイする
  2. 実行環境から除外したいファイルもあるので、archive_fileexcludes パラメータで個別に指定
  3. エントリポイント関数のファイルがルートに無いため、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!

image.png

おわりに

pip とも互換のある uv が採用されるのはうれしいので、この方向で uv をメインに使っても良いかなと思います。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?