Skip to content

Infrastructure

standoge edited this page Jul 12, 2026 · 2 revisions

Infrastructure

The GCP services the DocAI OCR API relies on, how each is configured, and how they interact. Everything runs on a single Compute Engine VM with Docker; there is no Kubernetes, no managed autoscaler, and (by default) no load balancer or TLS. Provisioning is scripted in deploy/gcp/ (01-provision.sh04-run.sh).

See also: Architecture · OCR Plugin · Job Manager.

Service map

flowchart TB
    Client([Client / curl])

    subgraph GCP["GCP project"]
        subgraph VM["Compute Engine VM (c4-standard-4, Ubuntu 24.04)"]
            Docker["Docker container<br/>ocrapi (FastAPI, port 8000)"]
            Data[("/data/jobs<br/>data disk 50 GB")]
        end

        DocAI["Document AI<br/>Document OCR processor"]
        GCS["Cloud Storage<br/>PROJECT-ocrapi-batch<br/>(legacy batch scratch)"]
        AR["Artifact Registry<br/>docker repo 'ocrapi'"]
        Log["Cloud Logging"]
        Mon["Cloud Monitoring"]
        SA["Service account<br/>ocrapi-sa@PROJECT.iam"]
    end

    Drive["Google Drive API<br/>Shared Drive folder"]

    Client -->|"HTTPS :8000 (TLS)"| Docker
    Docker --> Data
    Docker -->|processDocument| DocAI
    Docker -.->|batch path, unused| GCS
    Docker -->|resumable upload| Drive
    Docker -->|pull image| AR
    Docker --> Log
    Docker --> Mon

    VM -. "attached identity<br/>ADC + OAuth scopes" .- SA
    SA -->|IAM roles| DocAI
    SA -->|IAM roles| GCS
    SA -->|IAM roles| AR
    SA -->|"shared as Content Manager<br/>(not IAM)"| Drive
Loading

Services

Compute Engine (the VM)

The whole app runs as one Docker container on a single GCE instance managed by systemd (ocrapi.service).

Setting Default Notes
Machine type c4-standard-4 CPU is rarely the bottleneck; Document AI quota is
Image ubuntu-2404-lts-amd64
Boot disk 50 GB hyperdisk-balanced
Data disk 50 GB hyperdisk-balanced, mounted at /data Holds JOBS_DIR (/data/jobs), bind-mounted into the container
Network tag ocrapi Firewall rules target this tag
OS Login enabled SSH via gcloud compute ssh

The container is served over HTTPS on 0.0.0.0:8000, with TLS terminated in-process by uvicorn (--ssl-keyfile / --ssl-certfile) — no reverse proxy. A long-lived self-signed certificate is generated once by 02-vm-setup.sh and stored on the data disk at /data/tls (bind-mounted read-only into the container); this keeps client trust stable across container restarts and image redeploys. PDF uploads and OCR responses are therefore encrypted in transit. Clients trust /data/tls/cert.pem (--cacert) or use curl -k. The cert's SANs pin the VM's internal and external IPs — reserve a static IP or regenerate the cert if the external IP changes. See deploy/gcp/README.md for cert distribution and rotation.

Two firewall rules (INGRESS, on the ocrapi tag):

  • ocrapi-allow-httptcp:8000 (now carrying HTTPS), source APP_SOURCE_CIDR (defaults to 0.0.0.0/0; tighten to your intranet range)
  • ocrapi-allow-sshtcp:22, source ALLOWED_SSH_CIDR

Document AI (OCR engine)

The core OCR service. A Document OCR processor performs online processDocument calls on whole PDFs (sync) or per chunk (async). Retries with exponential backoff handle transient errors and RESOURCE_EXHAUSTED. See OCR Plugin for the client.

Config (.env) Purpose
GCP_PROJECT_ID Project containing the processor
GCP_LOCATION (us) Processor location; also derives the API endpoint {location}-documentai.googleapis.com
GCP_PROCESSOR_ID The Document OCR processor ID
  • API: documentai.googleapis.com (enabled by 01-provision.sh).
  • IAM: service account needs roles/documentai.apiUser on the project.
  • Quota: online processDocument pages/min (~120 sustained by default) is the real throughput ceiling. Read deploy/gcp/QUOTA.md before raising concurrency.

Google Drive API (result delivery)

Optional destination for finished searchable PDFs. Uploads use the Drive v3 resumable upload REST API with google.auth.transport.requests.AuthorizedSession — one session per upload so jobs finishing together can upload in parallel.

  • API: drive.googleapis.com (enabled by 01-provision.sh).
  • Access is NOT granted via IAM. Share the target folder with the service account email as Content Manager. The folder must live in a Shared Drive (service accounts have no personal My Drive quota).
  • OAuth scopes: the VM must carry cloud-platform and https://www.googleapis.com/auth/drive. cloud-platform alone covers Document AI/GCS but not Drive — a missing Drive scope yields 403 insufficient authentication scopes.
  • Config: DRIVE_SHARED_FOLDER_ID — default Shared Drive folder when a request omits folder_id. Use the full folder ID (typically 33 chars); a truncated ID causes 404 File not found.

Cloud Storage (legacy batch scratch)

A regional bucket gs://PROJECT-ocrapi-batch is provisioned for the Document AI batch code path (batch_process_from_gcs). The current async job pipeline does not use it — it is kept for future/optional batch OCR only.

Config / setting Value
GCS_BUCKET Bucket name (required by config even though unused by jobs)
Access control Uniform bucket-level access
Lifecycle 1-day delete rule (scratch objects auto-expire)
IAM roles/storage.objectAdmin on the bucket for the service account
BATCH_TIMEOUT_SECONDS (1800) Batch LRO polling timeout
BATCH_POLL_INTERVAL_SECONDS (10) Batch LRO poll interval

Artifact Registry (container images)

A Docker-format repository named ocrapi in the deploy region holds the app image. 03-build-and-push.sh builds linux/amd64 and pushes; 04-run.sh pins a tag and starts the service. The service account has roles/artifactregistry.reader to pull on the VM.

Cloud Logging & Monitoring (observability)

The container writes application logs to Cloud Logging and metrics to Cloud Monitoring. The service account has roles/logging.logWriter and roles/monitoring.metricWriter. On the VM, tail logs with journalctl -u ocrapi.service -f.

Service account (identity)

One service account, ocrapi-sa@PROJECT.iam.gserviceaccount.com, is the single identity for everything. On the VM it is used via Application Default Credentials (no JSON key in the container). Locally, point GOOGLE_APPLICATION_CREDENTIALS at a key file instead.

Access How it is granted
Document AI roles/documentai.apiUser (IAM, project)
Cloud Storage batch bucket roles/storage.objectAdmin (IAM, bucket)
Artifact Registry pull roles/artifactregistry.reader (IAM, project)
Cloud Logging / Monitoring roles/logging.logWriter, roles/monitoring.metricWriter (IAM, project)
Google Drive Not IAM — folder shared with the SA as Content Manager, plus the Drive OAuth scope on the VM

Enabled APIs

01-provision.sh enables: compute, documentai, drive, artifactregistry, iam, logging, monitoring, and storage.

Credentials: local vs GCE

Environment How credentials are obtained
Local dev JSON key file via GOOGLE_APPLICATION_CREDENTIALS
GCE production Attached VM service account via Application Default Credentials (no key file)

Housekeeping

Job folders under /data/jobs are not auto-deleted by the app. A systemd timer (ocrapi-cleanup.timerocrapi-cleanup.serviceocrapi-cleanup.sh) prunes old job folders daily and 10 minutes after boot (RETENTION_DAYS, default 7). Watch disk with df -h /data and du -sh /data/jobs.