|
| 1 | +```python exec |
| 2 | +import reflex as rx |
| 3 | +``` |
| 4 | + |
| 5 | +# Deploy to GCP Cloud Run |
| 6 | + |
| 7 | +The `reflex cloud deploy --gcp` command deploys a Reflex app to your own [Google Cloud Run](https://cloud.google.com/run) service. Reflex Cloud fetches a Cloud Run-ready Dockerfile and a `gcloud` deploy script, writes the Dockerfile into your project, and runs the script against the Google Cloud project you specify. The image is built on Cloud Build (so it works from any host OS, including Apple Silicon) and pushed to Artifact Registry. |
| 8 | + |
| 9 | +```md alert info |
| 10 | +# Enterprise tier only. |
| 11 | + |
| 12 | +Self-deploying to GCP Cloud Run is part of the **Enterprise tier** of Reflex Cloud. The control plane will return `403` to non-Enterprise tokens, and the CLI surfaces a clear error pointing at this. Contact [sales@reflex.dev](mailto:sales@reflex.dev) to upgrade. |
| 13 | +``` |
| 14 | + |
| 15 | +## Prerequisites |
| 16 | + |
| 17 | +Before running the command, install and authenticate the local tools the deploy script invokes: |
| 18 | + |
| 19 | +- `gcloud` — install from the [Google Cloud SDK docs](https://cloud.google.com/sdk/docs/install), then run: |
| 20 | + - `gcloud auth login` |
| 21 | + - `gcloud auth application-default login` |
| 22 | +- `docker` — required by `gcloud builds submit` for source upload. |
| 23 | +- `bash` — used to run the deploy script. |
| 24 | + |
| 25 | +You also need: |
| 26 | + |
| 27 | +- A GCP project with **billing enabled**. Without it, `gcloud services enable` fails with `UREQ_PROJECT_BILLING_NOT_FOUND`. |
| 28 | +- An Enterprise-tier Reflex Cloud subscription and a logged-in Reflex CLI (`reflex login`). |
| 29 | + |
| 30 | +## Quick start |
| 31 | + |
| 32 | +From the root of your Reflex app: |
| 33 | + |
| 34 | +```bash |
| 35 | +reflex cloud deploy --gcp \ |
| 36 | + --gcp-project my-gcp-project-id \ |
| 37 | + --service-name my-reflex-app |
| 38 | +``` |
| 39 | + |
| 40 | +The CLI will: |
| 41 | + |
| 42 | +1. Authenticate against Reflex Cloud and fetch the deploy manifest (Dockerfile + `gcloud` script). |
| 43 | +2. Print the manifest so you can review it. |
| 44 | +3. Write a `Dockerfile` into your project (after asking, if one already exists). |
| 45 | +4. Ask for confirmation, then run the `gcloud` script: enable the required APIs, create the Artifact Registry repository, build the image on Cloud Build, and deploy a public Cloud Run service. |
| 46 | + |
| 47 | +When it's done, you'll get a service URL like `https://my-reflex-app-<project-number>.us-central1.run.app`. |
| 48 | + |
| 49 | +## Options |
| 50 | + |
| 51 | +| Option | Default | Description | |
| 52 | +| --- | --- | --- | |
| 53 | +| `--gcp` | _(required)_ | Selects the GCP Cloud Run target. | |
| 54 | +| `--gcp-project` | _(required)_ | The GCP **project ID** to deploy into. Project numbers are **not** accepted by `gcloud artifacts repositories`; use the project ID. | |
| 55 | +| `--region` | `us-central1` | Cloud Run region. | |
| 56 | +| `--service-name` | `reflex-app` | Cloud Run service name. | |
| 57 | +| `--ar-repo` | `reflex` | Artifact Registry repository name (created on first deploy). | |
| 58 | +| `--version` | UTC timestamp (`YYYYMMDD-HHMMSS`) | Image version tag. | |
| 59 | +| `--source` | `.` | Directory containing the Reflex app and into which the Dockerfile is written. | |
| 60 | +| `--overwrite-dockerfile` | _off_ | Overwrite an existing `Dockerfile` without prompting. | |
| 61 | +| `--token` | _from `~/.reflex` config_ | Reflex authentication token. | |
| 62 | +| `--interactive / --no-interactive` | `--interactive` | Whether to prompt before overwriting the Dockerfile and running the script. | |
| 63 | +| `--dry-run` | _off_ | Print the manifest without writing the Dockerfile or running the script. | |
| 64 | +| `--loglevel` | `info` | Log verbosity. | |
| 65 | + |
| 66 | +## What gets created in your GCP project |
| 67 | + |
| 68 | +The deploy script enables these APIs (if not already enabled): |
| 69 | + |
| 70 | +- `cloudbuild.googleapis.com` |
| 71 | +- `run.googleapis.com` |
| 72 | +- `artifactregistry.googleapis.com` |
| 73 | + |
| 74 | +It then creates (idempotently) and uses: |
| 75 | + |
| 76 | +- An Artifact Registry Docker repository at `${REGION}-docker.pkg.dev/${GCP_PROJECT}/${AR_REPO}`. |
| 77 | +- A Cloud Build job that builds and pushes the image. |
| 78 | +- A Cloud Run service named `${SERVICE_NAME}`, deployed with `--allow-unauthenticated`, port 8080, 1 vCPU, 1 GiB memory, `--min-instances 1`, and `--session-affinity`. |
| 79 | + |
| 80 | +Re-running the command pushes a new image tag and rolls the Cloud Run service forward. |
| 81 | + |
| 82 | +## Security model |
| 83 | + |
| 84 | +The CLI runs the deploy script under a **restricted environment**. Only an explicit allowlist of host variables is forwarded to `bash` — things like `PATH`, `HOME`, `CLOUDSDK_*`, `DOCKER_*`, and proxy/TLS variables. Unrelated host secrets such as `AWS_*`, `GITHUB_TOKEN`, or arbitrary user variables are **not** forwarded, so a tampered or compromised manifest cannot exfiltrate them. |
| 85 | + |
| 86 | +You can preview the exact script and Dockerfile before anything runs by using `--dry-run`: |
| 87 | + |
| 88 | +```bash |
| 89 | +reflex cloud deploy --gcp \ |
| 90 | + --gcp-project my-gcp-project-id \ |
| 91 | + --dry-run |
| 92 | +``` |
| 93 | + |
| 94 | +## Non-interactive use (CI) |
| 95 | + |
| 96 | +For automated pipelines, pass `--no-interactive`, an explicit `--token`, and `--overwrite-dockerfile`: |
| 97 | + |
| 98 | +```bash |
| 99 | +reflex cloud deploy --gcp \ |
| 100 | + --gcp-project "$GCP_PROJECT_ID" \ |
| 101 | + --service-name my-reflex-app \ |
| 102 | + --token "$REFLEX_TOKEN" \ |
| 103 | + --no-interactive \ |
| 104 | + --overwrite-dockerfile |
| 105 | +``` |
| 106 | + |
| 107 | +In non-interactive mode the CLI will not prompt — it will refuse to overwrite an existing `Dockerfile` unless `--overwrite-dockerfile` is set, and it will exit non-zero if a token cannot be resolved. |
| 108 | + |
| 109 | +## Troubleshooting |
| 110 | + |
| 111 | +**`Flexgen denied the request (403). GCP Cloud Run deploys require an Enterprise tier subscription.`** |
| 112 | +Your account is not on the Enterprise tier. Contact [sales@reflex.dev](mailto:sales@reflex.dev). |
| 113 | + |
| 114 | +**`Billing must be enabled for activation of service(s) ...` (`UREQ_PROJECT_BILLING_NOT_FOUND`)** |
| 115 | +Attach a billing account to the GCP project, or use a different `--gcp-project`. |
| 116 | + |
| 117 | +**`The value of '--project' flag was set to Project number. To use this command, set it to PROJECT ID instead.`** |
| 118 | +Pass the project ID (e.g. `my-app-123456`), not the numeric project number. |
| 119 | + |
| 120 | +**`No active GCP account found.`** |
| 121 | +Run `gcloud auth login` and `gcloud auth application-default login`. |
| 122 | + |
| 123 | +**`The 'gcloud' / 'docker' / 'bash' CLI was not found on PATH.`** |
| 124 | +Install the missing tool and ensure it's on `PATH` for the shell you're invoking the CLI from. |
0 commit comments