[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81681":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":15,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":24,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":30,"readmeContent":31,"aiSummary":32,"trendingCount":16,"starSnapshotCount":16,"syncStatus":33,"lastSyncTime":34,"discoverSource":35},81681,"floci-gcp","floci-io\u002Ffloci-gcp","floci-io","Light, fluffy, and always free - GCP Local Emulator","https:\u002F\u002Ffloci.io",null,"Java",54,12,27,3,0,19,28,14,61.64,"MIT License",false,"main",true,[26,27,5,28,29],"docker","floci","gcp","google","2026-06-12 04:01:34","\u003Cp align=\"center\">\n  \u003Cimg src=\"floci_banner.svg\" alt=\"floci-gcp\"\u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cstrong>Light, fluffy, and always free — GCP Local Emulator\u003C\u002Fstrong>\u003Cbr \u002F>\n  No account. No auth token. No feature gates. Just \u003Ccode>docker compose up\u003C\u002Fcode>.\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffloci-io\u002Ffloci-gcp\u002Freleases\u002Flatest\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Fhectorvent\u002Ffloci-gcp?label=latest%20release&color=blue\" alt=\"Latest Release\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffloci-io\u002Ffloci-gcp\u002Factions\u002Fworkflows\u002Frelease.yml\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fhectorvent\u002Ffloci-gcp\u002Frelease.yml?label=build\" alt=\"Build Status\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fhub.docker.com\u002Fr\u002Ffloci\u002Ffloci-gcp\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fpulls\u002Ffloci\u002Ffloci-gcp?label=docker%20pulls\" alt=\"Docker Pulls\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fhub.docker.com\u002Fr\u002Ffloci\u002Ffloci-gcp\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fimage-size\u002Ffloci\u002Ffloci-gcp\u002Flatest?label=image%20size\" alt=\"Docker Image Size\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-green\" alt=\"License: MIT\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffloci-io\u002Ffloci-gcp\u002Fstargazers\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Fhectorvent\u002Ffloci-gcp?style=flat\" alt=\"GitHub Stars\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"#quick-start\">Quick Start\u003C\u002Fa> ·\n  \u003Ca href=\"#features\">Features\u003C\u002Fa> ·\n  \u003Ca href=\"#supported-services\">Services\u003C\u002Fa> ·\n  \u003Ca href=\"#sdk-integration\">SDKs\u003C\u002Fa> ·\n  \u003Ca href=\"#testcontainers\">Testcontainers\u003C\u002Fa> ·\n  \u003Ca href=\"#compatibility-testing\">Compatibility\u003C\u002Fa> ·\n  \u003Ca href=\"https:\u002F\u002Ffloci.io\u002Ffloci-gcp\u002F\">Docs\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## What is floci-gcp?\n\nfloci-gcp is a free, open-source local GCP emulator for development, testing, and CI.\n\nIt gives you GCP-shaped services on your machine without requiring a cloud account, auth token, or paid feature gates. Point your GCP SDK, gcloud CLI, Terraform, or test suite at `http:\u002F\u002Flocalhost:4588` and keep your existing workflows.\n\nfloci-gcp is named after [floccus](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCirrocumulus_floccus), the cloud formation that looks like popcorn.\n\n## Quick Start\n\n```yaml\n# docker-compose.yml\nservices:\n  floci-gcp:\n    image: floci\u002Ffloci-gcp:latest\n    ports:\n      - \"4588:4588\"\n    volumes:\n      - .\u002Fdata:\u002Fapp\u002Fdata\n    environment:\n      FLOCI_GCP_HOSTNAME: floci-gcp\n      FLOCI_GCP_BASE_URL: http:\u002F\u002Ffloci-gcp:4588\n```\n\n```bash\ndocker compose up -d\n```\n\nExport the GCP emulator environment variables:\n\n```bash\nexport PUBSUB_EMULATOR_HOST=localhost:4588\nexport FIRESTORE_EMULATOR_HOST=localhost:4588\nexport DATASTORE_EMULATOR_HOST=localhost:4588\nexport STORAGE_EMULATOR_HOST=http:\u002F\u002Flocalhost:4588\nexport SECRET_MANAGER_EMULATOR_HOST=localhost:4588\nexport GOOGLE_CLOUD_PROJECT=floci-local\n```\n\nAll GCP services are available at `http:\u002F\u002Flocalhost:4588`. Credentials are not validated.\n\n\u003Cdetails>\n\u003Csummary>Using Docker directly?\u003C\u002Fsummary>\n\n```bash\ndocker run -d --name floci-gcp \\\n  -p 4588:4588 \\\n  floci\u002Ffloci-gcp:latest\n```\n\n\u003C\u002Fdetails>\n\n## Features\n\n\u003Cdetails open>\n\u003Csummary>\u003Cstrong>Local GCP without the cloud account\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nRun GCP-compatible services locally without a GCP account, service account key, or paid feature gates.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Single port for everything\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nAll GCP services — gRPC and REST — share a single port (`4588`) via HTTP\u002F2 ALPN negotiation. No per-service daemon setup, no port management.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Real GCP wire protocols\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nfloci-gcp speaks the same protocols as real GCP: protobuf-over-gRPC for Pub\u002FSub, Firestore, and Secret Manager; binary HTTP\u002Fprotobuf for Datastore; REST XML and JSON for Cloud Storage. Existing SDK calls work without modification.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Fast enough for CI\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nThe native image starts in milliseconds and keeps idle memory low, making it practical for local development and test pipelines.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Configurable persistence\u003C\u002Fstrong>\u003C\u002Fsummary>\n\nChoose from in-memory, persistent, hybrid, and write-ahead log storage depending on the durability profile you need.\n\n\u003C\u002Fdetails>\n\n## Why floci-gcp?\n\nGCP's official emulators are fragmented — each service ships its own binary, runs on a different port, and requires separate setup. floci-gcp unifies them under a single port.\n\n| Capability | floci-gcp | GCP official emulators |\n|---|:---:|:---:|\n| Single port for all services | ✅ | ❌ |\n| gRPC + REST on the same port | ✅ | ❌ |\n| No GCP account required | ✅ | ✅ |\n| Pub\u002FSub | ✅ | ✅ |\n| Firestore | ✅ | ✅ |\n| Datastore | ✅ | ✅ |\n| Cloud Storage (GCS) | ✅ | ⚠️ Limited |\n| Secret Manager | ✅ | ❌ |\n| IAM | ✅ | ❌ |\n| Managed Kafka | ✅ | ❌ |\n| Native binary | ✅ | ❌ |\n\n## Architecture Overview\n\n```mermaid\nflowchart LR\n    Client[\"GCP SDK \u002F gcloud CLI\"]\n\n    subgraph FlociGCP [\"floci-gcp, port 4588\"]\n        Router[\"HTTP\u002F2 Router\\nALPN negotiation\"]\n\n        subgraph GRPC [\"gRPC services\"]\n            A[\"Pub\u002FSub\\nFirestore\\nSecret Manager\"]\n        end\n\n        subgraph REST [\"REST services\"]\n            B[\"Cloud Storage\\nIAM\\nDatastore\"]\n        end\n\n        subgraph Docker [\"Docker-backed\"]\n            C[\"Managed Kafka\\n(Redpanda)\"]\n        end\n\n        Router --> GRPC\n        Router --> REST\n        Router --> Docker\n        GRPC & REST --> Store[(\"StorageBackend\\nmemory · hybrid · persistent · wal\")]\n    end\n\n    DockerEngine[\"Docker Engine\"]\n    Client -->|\"HTTP\u002F2 :4588\\nGCP wire protocols\"| Router\n    Docker -->|\"Docker API\"| DockerEngine\n```\n\n## Supported Services\n\nfloci-gcp emulates GCP services across storage, messaging, identity, and managed infrastructure.\n\n| Category | Services |\n|---|---|\n| Object and document storage | Cloud Storage (GCS), Firestore, Datastore |\n| Messaging | Pub\u002FSub, Managed Kafka |\n| Security and identity | Secret Manager, IAM |\n\n\u003Cdetails>\n\u003Csummary>Detailed service notes\u003C\u002Fsummary>\n\n| Service | Protocol | Notable features |\n|---|---|---|\n| **Cloud Storage (GCS)** | REST XML + REST JSON | Buckets, objects, multipart upload, object compose, ACLs, bucket IAM, conditional requests (preconditions), versioning, lifecycle, CORS, pre-signed URLs (V4) |\n| **Pub\u002FSub** | gRPC | Topics, subscriptions, publish, pull, streaming pull, push delivery, snapshots, seek, field masks on update |\n| **Firestore** | gRPC | Documents, collections, queries (all operators), field transforms, aggregation (COUNT), transactions, batch writes, real-time listeners (`listen` stream) |\n| **Datastore** | HTTP\u002Fprotobuf | Entities, structured queries, GQL queries, aggregation (COUNT), transactions, GQL named\u002Fpositional bindings |\n| **Secret Manager** | gRPC | Secrets, versioning, access, `versions\u002Flatest` alias, disable\u002Fenable\u002Fdestroy, IAM bindings |\n| **IAM** | REST JSON | Service accounts, RSA-2048 key pairs (JSON key file format), policy bindings, `SignBlob` (V4 signed URLs) |\n| **Managed Kafka** | REST JSON | Clusters, topics, consumer groups; Redpanda-backed or mock mode |\n\n\u003C\u002Fdetails>\n\n## Persistence & Storage Modes\n\nfloci-gcp supports flexible storage modes. Configure globally via `FLOCI_GCP_STORAGE_MODE`.\n\n| Mode | Behavior | Best for | Durability |\n|:---:|---|---|:---:|\n| **`memory`** | **(Default)** Entirely in-RAM. Lost on container stop. | Speed, CI pipelines | ❌ None |\n| **`persistent`** | Every write goes directly to disk synchronously. | Durable local dev | ✅ Good |\n| **`hybrid`** | In-memory with async flush every 5 seconds. | Balance of speed and safety | ✅ Good |\n| **`wal`** | Write-Ahead Log. Every mutation written to disk immediately. | Maximum durability | 💎 Highest |\n\nUse `memory` for fast CI runs. Use `hybrid` when you want state preserved across container restarts.\n\n## Multi-Project Isolation\n\nGCP resource names follow `projects\u002F{project}\u002F...`. floci-gcp uses the project ID as the multi-tenancy boundary — resources in `project-a` are invisible to `project-b`.\n\nThe project ID is resolved in this order:\n1. URL path segment `projects\u002F{project}\u002F...`\n2. `x-goog-request-params` header (`project=...`)\n3. `FLOCI_GCP_DEFAULT_PROJECT_ID` fallback (default: `floci-local`)\n\n```bash\n# Two projects, full isolation\nexport PUBSUB_EMULATOR_HOST=localhost:4588\n\ngcloud pubsub topics create my-topic --project=project-a\ngcloud pubsub topics create my-topic --project=project-b\n\n# Each project has its own independent topic\n```\n\n## SDK Integration\n\nPoint your existing GCP SDK at `http:\u002F\u002Flocalhost:4588`.\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Java (GCP SDK)\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```java\n\u002F\u002F Pub\u002FSub\nManagedChannel channel = ManagedChannelBuilder\n    .forTarget(\"localhost:4588\")\n    .usePlaintext()\n    .build();\n\nTransportChannelProvider channelProvider =\n    FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel));\nCredentialsProvider credentialsProvider = NoCredentialsProvider.create();\n\nTopicAdminClient topicClient = TopicAdminClient.create(\n    TopicAdminSettings.newBuilder()\n        .setTransportChannelProvider(channelProvider)\n        .setCredentialsProvider(credentialsProvider)\n        .build());\n\ntopicClient.createTopic(TopicName.of(\"floci-local\", \"my-topic\"));\n```\n\n```java\n\u002F\u002F Cloud Storage\nStorage storage = StorageOptions.newBuilder()\n    .setHost(\"http:\u002F\u002Flocalhost:4588\")\n    .setProjectId(\"floci-local\")\n    .setCredentials(NoCredentials.getInstance())\n    .build()\n    .getService();\n\nstorage.create(BucketInfo.of(\"my-bucket\"));\nstorage.create(BlobInfo.newBuilder(\"my-bucket\", \"hello.txt\").build(),\n    \"hello from floci-gcp\".getBytes());\n```\n\n```java\n\u002F\u002F Firestore\nFirestoreOptions options = FirestoreOptions.newBuilder()\n    .setHost(\"localhost:4588\")\n    .setProjectId(\"floci-local\")\n    .setCredentials(NoCredentials.getInstance())\n    .build();\n\nFirestore db = options.getService();\ndb.collection(\"users\").add(Map.of(\"name\", \"Alice\", \"age\", 30)).get();\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Python (google-cloud)\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```python\nimport os\nos.environ[\"PUBSUB_EMULATOR_HOST\"] = \"localhost:4588\"\n\nfrom google.cloud import pubsub_v1\n\npublisher = pubsub_v1.PublisherClient()\ntopic_path = publisher.topic_path(\"floci-local\", \"my-topic\")\npublisher.create_topic(request={\"name\": topic_path})\nfuture = publisher.publish(topic_path, b\"hello from floci-gcp\")\nfuture.result()\n```\n\n```python\nimport os\nos.environ[\"STORAGE_EMULATOR_HOST\"] = \"http:\u002F\u002Flocalhost:4588\"\n\nfrom google.cloud import storage\n\nclient = storage.Client(project=\"floci-local\")\nbucket = client.bucket(\"my-bucket\")\nclient.create_bucket(bucket)\n\nblob = bucket.blob(\"hello.txt\")\nblob.upload_from_string(\"hello from floci-gcp\")\nprint(blob.download_as_text())\n```\n\n```python\nimport os\nos.environ[\"FIRESTORE_EMULATOR_HOST\"] = \"localhost:4588\"\n\nfrom google.cloud import firestore\n\ndb = firestore.Client(project=\"floci-local\")\ndb.collection(\"users\").add({\"name\": \"Alice\", \"age\": 30})\ndocs = db.collection(\"users\").where(\"name\", \"==\", \"Alice\").stream()\nfor doc in docs:\n    print(doc.to_dict())\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Node.js\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```javascript\nimport { PubSub } from \"@google-cloud\u002Fpubsub\";\n\nprocess.env.PUBSUB_EMULATOR_HOST = \"localhost:4588\";\n\nconst pubsub = new PubSub({ projectId: \"floci-local\" });\nawait pubsub.createTopic(\"my-topic\");\nconst [subscription] = await pubsub.topic(\"my-topic\").createSubscription(\"my-sub\");\n```\n\n```javascript\nimport { Storage } from \"@google-cloud\u002Fstorage\";\n\nconst storage = new Storage({\n  apiEndpoint: \"http:\u002F\u002Flocalhost:4588\",\n  projectId: \"floci-local\",\n});\n\nawait storage.createBucket(\"my-bucket\");\nawait storage.bucket(\"my-bucket\").file(\"hello.txt\").save(\"hello from floci-gcp\");\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Go\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n\n    \"cloud.google.com\u002Fgo\u002Fpubsub\"\n    \"google.golang.org\u002Fapi\u002Foption\"\n    \"google.golang.org\u002Fgrpc\"\n    \"google.golang.org\u002Fgrpc\u002Fcredentials\u002Finsecure\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    conn, err := grpc.Dial(\"localhost:4588\", grpc.WithTransportCredentials(insecure.NewCredentials()))\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    client, err := pubsub.NewClient(ctx, \"floci-local\",\n        option.WithGRPCConn(conn))\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer client.Close()\n\n    topic, err := client.CreateTopic(ctx, \"my-topic\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println(\"Created topic:\", topic.ID())\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Bash (gcloud CLI)\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```bash\nexport PUBSUB_EMULATOR_HOST=localhost:4588\ngcloud config set project floci-local\n\n# Pub\u002FSub\ngcloud pubsub topics create my-topic\ngcloud pubsub subscriptions create my-sub --topic=my-topic\ngcloud pubsub topics publish my-topic --message=\"hello from floci-gcp\"\ngcloud pubsub subscriptions pull my-sub --auto-ack\n\n# Cloud Storage\nexport STORAGE_EMULATOR_HOST=http:\u002F\u002Flocalhost:4588\ngcloud storage buckets create gs:\u002F\u002Fmy-bucket\necho \"hello\" | gcloud storage cp - gs:\u002F\u002Fmy-bucket\u002Fhello.txt\ngcloud storage ls gs:\u002F\u002Fmy-bucket\n\n# Secret Manager\nexport SECRET_MANAGER_EMULATOR_HOST=localhost:4588\ngcloud secrets create my-secret --replication-policy=automatic\necho -n \"my-value\" | gcloud secrets versions add my-secret --data-file=-\ngcloud secrets versions access latest --secret=my-secret\n```\n\n\u003C\u002Fdetails>\n\n## Testcontainers\n\nUse `GenericContainer` to start an isolated floci-gcp instance directly from your tests. This avoids shared state, manual daemon setup, and port conflicts.\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Java\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```java\n@Testcontainers\nclass PubSubIntegrationTest {\n\n    @Container\n    static GenericContainer\u003C?> flociGcp = new GenericContainer\u003C>(\"floci\u002Ffloci-gcp:latest\")\n        .withExposedPorts(4588)\n        .waitingFor(Wait.forHttp(\"\u002F_floci\u002Fhealth\").forPort(4588));\n\n    static TopicAdminClient topicClient;\n\n    @BeforeAll\n    static void setup() throws Exception {\n        String host = flociGcp.getHost();\n        int port = flociGcp.getMappedPort(4588);\n\n        ManagedChannel channel = ManagedChannelBuilder\n            .forAddress(host, port)\n            .usePlaintext()\n            .build();\n\n        topicClient = TopicAdminClient.create(\n            TopicAdminSettings.newBuilder()\n                .setTransportChannelProvider(\n                    FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)))\n                .setCredentialsProvider(NoCredentialsProvider.create())\n                .build());\n    }\n\n    @Test\n    void shouldCreateTopic() {\n        topicClient.createTopic(TopicName.of(\"floci-local\", \"test-topic\"));\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Python\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n```python\nimport pytest\nfrom testcontainers.core.container import DockerContainer\nfrom google.cloud import pubsub_v1\n\n\n@pytest.fixture(scope=\"session\")\ndef floci_gcp():\n    with DockerContainer(\"floci\u002Ffloci-gcp:latest\").with_exposed_ports(4588) as container:\n        container.get_exposed_port(4588)  # wait for startup\n        yield container\n\n\ndef test_pubsub(floci_gcp):\n    port = floci_gcp.get_exposed_port(4588)\n    host = floci_gcp.get_container_host_ip()\n\n    import os\n    os.environ[\"PUBSUB_EMULATOR_HOST\"] = f\"{host}:{port}\"\n\n    publisher = pubsub_v1.PublisherClient()\n    topic_path = publisher.topic_path(\"floci-local\", \"test-topic\")\n    publisher.create_topic(request={\"name\": topic_path})\n```\n\n\u003C\u002Fdetails>\n\n## Compatibility Testing\n\nThe [`compatibility-tests`](.\u002Fcompatibility-tests\u002F) directory validates floci-gcp across SDKs and IaC tools.\n\n| Module | Language \u002F Tool | SDK \u002F Client |\n|---|---|---|\n| `sdk-test-java` | Java | GCP SDK for Java |\n| `sdk-test-node` | Node.js | `@google-cloud\u002F*` |\n| `sdk-test-python` | Python | `google-cloud-*` |\n| `sdk-test-go` | Go | `cloud.google.com\u002Fgo\u002F*` |\n| `compat-terraform` | Terraform | Google provider |\n| `compat-opentofu` | OpenTofu | Google provider |\n\nRun the full suite:\n\n```bash\ncd compatibility-tests && just test-java\ncd compatibility-tests && just test-go\ncd compatibility-tests && just test-terraform\n```\n\n## Image Tags\n\nEvery tag combines a variant and a channel.\n\n| Channel | Tag |\n|---|---|\n| Release, floating | `latest` |\n| Release, pinned | `x.y.z` |\n| Nightly, floating | `nightly` |\n| Nightly, dated | `nightly-mmddyyyy` |\n\nUse `latest` for stable releases, a pinned version for reproducible builds, and `nightly` to track `main`.\n\n```yaml\n# Recommended\nimage: floci\u002Ffloci-gcp:latest\n\n# Pinned release\nimage: floci\u002Ffloci-gcp:1.0.0\n\n# Track main\nimage: floci\u002Ffloci-gcp:nightly\n```\n\n## Configuration\n\nAll settings are overridable via environment variables (`FLOCI_GCP_` prefix).\n\n| Variable | Default | Description |\n|---|---|---|\n| `FLOCI_GCP_PORT` | `4588` | Port for all services (gRPC + REST) |\n| `FLOCI_GCP_DEFAULT_PROJECT_ID` | `floci-local` | Default GCP project ID |\n| `FLOCI_GCP_BASE_URL` | `http:\u002F\u002Flocalhost:4588` | Base URL returned in service responses |\n| `FLOCI_GCP_HOSTNAME` | *(unset)* | Hostname to use in returned URLs when running inside Docker Compose |\n| `FLOCI_GCP_STORAGE_MODE` | `memory` | Storage mode: `memory` · `persistent` · `hybrid` · `wal` |\n| `FLOCI_GCP_STORAGE_PERSISTENT_PATH` | `.\u002Fdata` | Directory for persisted state |\n| `FLOCI_GCP_SERVICES_GCS_ENABLED` | `true` | Enable\u002Fdisable Cloud Storage |\n| `FLOCI_GCP_SERVICES_PUBSUB_ENABLED` | `true` | Enable\u002Fdisable Pub\u002FSub |\n| `FLOCI_GCP_SERVICES_FIRESTORE_ENABLED` | `true` | Enable\u002Fdisable Firestore |\n| `FLOCI_GCP_SERVICES_DATASTORE_ENABLED` | `true` | Enable\u002Fdisable Datastore |\n| `FLOCI_GCP_SERVICES_IAM_ENABLED` | `true` | Enable\u002Fdisable IAM |\n| `FLOCI_GCP_SERVICES_SECRETMANAGER_ENABLED` | `true` | Enable\u002Fdisable Secret Manager |\n| `FLOCI_GCP_SERVICES_KAFKA_ENABLED` | `true` | Enable\u002Fdisable Managed Kafka |\n| `FLOCI_GCP_SERVICES_KAFKA_MOCK` | `false` | Use mock mode (no Docker; returns `ACTIVE` immediately) |\n| `FLOCI_GCP_DNS_EXTRA_SUFFIXES` | *(unset)* | Extra DNS suffixes for embedded DNS (comma-separated) |\n\n### Multi-container Docker Compose\n\nWhen your application runs in a different container, set `FLOCI_GCP_HOSTNAME` to the floci-gcp service name so returned URLs resolve correctly from other containers.\n\n```yaml\nservices:\n  floci-gcp:\n    image: floci\u002Ffloci-gcp:latest\n    ports:\n      - \"4588:4588\"\n    environment:\n      FLOCI_GCP_HOSTNAME: floci-gcp\n      FLOCI_GCP_BASE_URL: http:\u002F\u002Ffloci-gcp:4588\n\n  my-app:\n    environment:\n      PUBSUB_EMULATOR_HOST: floci-gcp:4588\n      FIRESTORE_EMULATOR_HOST: floci-gcp:4588\n      STORAGE_EMULATOR_HOST: http:\u002F\u002Ffloci-gcp:4588\n    depends_on:\n      - floci-gcp\n```\n\n---\n\n## Contributors\n\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffloci-io\u002Ffloci-gcp\u002Fgraphs\u002Fcontributors\">\n  \u003Cimg src=\"https:\u002F\u002Fcontrib.rocks\u002Fimage?repo=hectorvent\u002Ffloci-gcp\" \u002F>\n\u003C\u002Fa>\n\n---\n\n## License\n\nMIT — use it however you want.\n","floci-gcp 是一个轻量级且免费的本地 GCP 仿真器，适用于开发、测试和持续集成。它允许用户在本地运行类似 GCP 的服务，而无需拥有云账户、认证令牌或付费功能。通过简单的 `docker compose up` 命令即可启动，支持多种 GCP 服务如 Pub\u002FSub, Firestore, Datastore, Storage 和 Secret Manager 等，并能直接与 GCP SDK、gcloud CLI 或 Terraform 集成。此项目非常适合希望在没有真实 GCP 资源的情况下进行应用开发与调试的开发者使用。",2,"2026-06-11 04:05:56","CREATED_QUERY"]