Deploy GCP Cloud Run Services

The gcp:cloudrunv2/service:Service resource, part of the Pulumi GCP provider, defines a Cloud Run service that manages container revisions, traffic routing, and scaling behavior. This guide focuses on four capabilities: container deployment with resource limits, VPC networking for private resource access, volume mounts for databases and secrets, and health probes with multi-container configurations.

Cloud Run services reference container images from registries and may connect to VPC networks, Cloud SQL instances, or Secret Manager. The examples are intentionally small. Combine them with your own networking, IAM roles, and storage infrastructure.

Deploy a container with scaling limits

Most deployments start with a container image and basic scaling configuration to control instance counts.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    ingress: "INGRESS_TRAFFIC_ALL",
    scaling: {
        maxInstanceCount: 100,
    },
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    ingress="INGRESS_TRAFFIC_ALL",
    scaling={
        "max_instance_count": 100,
    },
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Ingress:            pulumi.String("INGRESS_TRAFFIC_ALL"),
			Scaling: &cloudrunv2.ServiceScalingArgs{
				MaxInstanceCount: pulumi.Int(100),
			},
			Template: &cloudrunv2.ServiceTemplateArgs{
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Ingress = "INGRESS_TRAFFIC_ALL",
        Scaling = new Gcp.CloudRunV2.Inputs.ServiceScalingArgs
        {
            MaxInstanceCount = 100,
        },
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceScalingArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .ingress("INGRESS_TRAFFIC_ALL")
            .scaling(ServiceScalingArgs.builder()
                .maxInstanceCount(100)
                .build())
            .template(ServiceTemplateArgs.builder()
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      ingress: INGRESS_TRAFFIC_ALL
      scaling:
        maxInstanceCount: 100
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello

The template property defines the container specification that Cloud Run uses to create revisions. The image points to your container registry, and scaling.maxInstanceCount caps the number of concurrent instances. The ingress property controls whether traffic comes from the internet, internal sources only, or load balancers.

Set CPU and memory resource limits

Applications with specific resource requirements need explicit limits to ensure predictable performance.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    ingress: "INGRESS_TRAFFIC_ALL",
    template: {
        healthCheckDisabled: true,
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
            resources: {
                limits: {
                    cpu: "2",
                    memory: "1024Mi",
                },
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    ingress="INGRESS_TRAFFIC_ALL",
    template={
        "health_check_disabled": True,
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
            "resources": {
                "limits": {
                    "cpu": "2",
                    "memory": "1024Mi",
                },
            },
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Ingress:            pulumi.String("INGRESS_TRAFFIC_ALL"),
			Template: &cloudrunv2.ServiceTemplateArgs{
				HealthCheckDisabled: pulumi.Bool(true),
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						Resources: &cloudrunv2.ServiceTemplateContainerResourcesArgs{
							Limits: pulumi.StringMap{
								"cpu":    pulumi.String("2"),
								"memory": pulumi.String("1024Mi"),
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Ingress = "INGRESS_TRAFFIC_ALL",
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            HealthCheckDisabled = true,
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    Resources = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerResourcesArgs
                    {
                        Limits = 
                        {
                            { "cpu", "2" },
                            { "memory", "1024Mi" },
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .ingress("INGRESS_TRAFFIC_ALL")
            .template(ServiceTemplateArgs.builder()
                .healthCheckDisabled(true)
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .resources(ServiceTemplateContainerResourcesArgs.builder()
                        .limits(Map.ofEntries(
                            Map.entry("cpu", "2"),
                            Map.entry("memory", "1024Mi")
                        ))
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      ingress: INGRESS_TRAFFIC_ALL
      template:
        healthCheckDisabled: true
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
            resources:
              limits:
                cpu: '2'
                memory: 1024Mi

The resources.limits block sets CPU cores and memory allocation for each container instance. Cloud Run uses these limits for billing and scheduling. Setting healthCheckDisabled to true skips default health checks when you provide custom probes.

Connect to Cloud SQL with mounted volumes

Services that need database access can mount Cloud SQL instances as volumes for Unix socket connections.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const secret = new gcp.secretmanager.Secret("secret", {
    secretId: "secret-1",
    replication: {
        auto: {},
    },
});
const secret_version_data = new gcp.secretmanager.SecretVersion("secret-version-data", {
    secret: secret.name,
    secretData: "secret-data",
});
const instance = new gcp.sql.DatabaseInstance("instance", {
    name: "cloudrun-sql",
    region: "us-central1",
    databaseVersion: "MYSQL_5_7",
    settings: {
        tier: "db-f1-micro",
    },
    deletionProtection: true,
});
const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    ingress: "INGRESS_TRAFFIC_ALL",
    scaling: {
        maxInstanceCount: 2,
    },
    template: {
        volumes: [{
            name: "cloudsql",
            cloudSqlInstance: {
                instances: [instance.connectionName],
            },
        }],
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
            envs: [
                {
                    name: "FOO",
                    value: "bar",
                },
                {
                    name: "SECRET_ENV_VAR",
                    valueSource: {
                        secretKeyRef: {
                            secret: secret.secretId,
                            version: "1",
                        },
                    },
                },
            ],
            volumeMounts: [{
                name: "cloudsql",
                mountPath: "/cloudsql",
            }],
        }],
    },
    traffics: [{
        type: "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST",
        percent: 100,
    }],
}, {
    dependsOn: [secret_version_data],
});
const project = gcp.organizations.getProject({});
const secret_access = new gcp.secretmanager.SecretIamMember("secret-access", {
    secretId: secret.id,
    role: "roles/secretmanager.secretAccessor",
    member: project.then(project => `serviceAccount:${project.number}-compute@developer.gserviceaccount.com`),
}, {
    dependsOn: [secret],
});
import pulumi
import pulumi_gcp as gcp

secret = gcp.secretmanager.Secret("secret",
    secret_id="secret-1",
    replication={
        "auto": {},
    })
secret_version_data = gcp.secretmanager.SecretVersion("secret-version-data",
    secret=secret.name,
    secret_data="secret-data")
instance = gcp.sql.DatabaseInstance("instance",
    name="cloudrun-sql",
    region="us-central1",
    database_version="MYSQL_5_7",
    settings={
        "tier": "db-f1-micro",
    },
    deletion_protection=True)
default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    ingress="INGRESS_TRAFFIC_ALL",
    scaling={
        "max_instance_count": 2,
    },
    template={
        "volumes": [{
            "name": "cloudsql",
            "cloud_sql_instance": {
                "instances": [instance.connection_name],
            },
        }],
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
            "envs": [
                {
                    "name": "FOO",
                    "value": "bar",
                },
                {
                    "name": "SECRET_ENV_VAR",
                    "value_source": {
                        "secret_key_ref": {
                            "secret": secret.secret_id,
                            "version": "1",
                        },
                    },
                },
            ],
            "volume_mounts": [{
                "name": "cloudsql",
                "mount_path": "/cloudsql",
            }],
        }],
    },
    traffics=[{
        "type": "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST",
        "percent": 100,
    }],
    opts = pulumi.ResourceOptions(depends_on=[secret_version_data]))
project = gcp.organizations.get_project()
secret_access = gcp.secretmanager.SecretIamMember("secret-access",
    secret_id=secret.id,
    role="roles/secretmanager.secretAccessor",
    member=f"serviceAccount:{project.number}-compute@developer.gserviceaccount.com",
    opts = pulumi.ResourceOptions(depends_on=[secret]))
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/sql"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		secret, err := secretmanager.NewSecret(ctx, "secret", &secretmanager.SecretArgs{
			SecretId: pulumi.String("secret-1"),
			Replication: &secretmanager.SecretReplicationArgs{
				Auto: &secretmanager.SecretReplicationAutoArgs{},
			},
		})
		if err != nil {
			return err
		}
		secret_version_data, err := secretmanager.NewSecretVersion(ctx, "secret-version-data", &secretmanager.SecretVersionArgs{
			Secret:     secret.Name,
			SecretData: pulumi.String("secret-data"),
		})
		if err != nil {
			return err
		}
		instance, err := sql.NewDatabaseInstance(ctx, "instance", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("cloudrun-sql"),
			Region:          pulumi.String("us-central1"),
			DatabaseVersion: pulumi.String("MYSQL_5_7"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier: pulumi.String("db-f1-micro"),
			},
			DeletionProtection: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Ingress:            pulumi.String("INGRESS_TRAFFIC_ALL"),
			Scaling: &cloudrunv2.ServiceScalingArgs{
				MaxInstanceCount: pulumi.Int(2),
			},
			Template: &cloudrunv2.ServiceTemplateArgs{
				Volumes: cloudrunv2.ServiceTemplateVolumeArray{
					&cloudrunv2.ServiceTemplateVolumeArgs{
						Name: pulumi.String("cloudsql"),
						CloudSqlInstance: &cloudrunv2.ServiceTemplateVolumeCloudSqlInstanceArgs{
							Instances: pulumi.StringArray{
								instance.ConnectionName,
							},
						},
					},
				},
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						Envs: cloudrunv2.ServiceTemplateContainerEnvArray{
							&cloudrunv2.ServiceTemplateContainerEnvArgs{
								Name:  pulumi.String("FOO"),
								Value: pulumi.String("bar"),
							},
							&cloudrunv2.ServiceTemplateContainerEnvArgs{
								Name: pulumi.String("SECRET_ENV_VAR"),
								ValueSource: &cloudrunv2.ServiceTemplateContainerEnvValueSourceArgs{
									SecretKeyRef: &cloudrunv2.ServiceTemplateContainerEnvValueSourceSecretKeyRefArgs{
										Secret:  secret.SecretId,
										Version: pulumi.String("1"),
									},
								},
							},
						},
						VolumeMounts: cloudrunv2.ServiceTemplateContainerVolumeMountArray{
							&cloudrunv2.ServiceTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("cloudsql"),
								MountPath: pulumi.String("/cloudsql"),
							},
						},
					},
				},
			},
			Traffics: cloudrunv2.ServiceTrafficArray{
				&cloudrunv2.ServiceTrafficArgs{
					Type:    pulumi.String("TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"),
					Percent: pulumi.Int(100),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			secret_version_data,
		}))
		if err != nil {
			return err
		}
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = secretmanager.NewSecretIamMember(ctx, "secret-access", &secretmanager.SecretIamMemberArgs{
			SecretId: secret.ID(),
			Role:     pulumi.String("roles/secretmanager.secretAccessor"),
			Member:   pulumi.Sprintf("serviceAccount:%v-compute@developer.gserviceaccount.com", project.Number),
		}, pulumi.DependsOn([]pulumi.Resource{
			secret,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var secret = new Gcp.SecretManager.Secret("secret", new()
    {
        SecretId = "secret-1",
        Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
        {
            Auto = null,
        },
    });

    var secret_version_data = new Gcp.SecretManager.SecretVersion("secret-version-data", new()
    {
        Secret = secret.Name,
        SecretData = "secret-data",
    });

    var instance = new Gcp.Sql.DatabaseInstance("instance", new()
    {
        Name = "cloudrun-sql",
        Region = "us-central1",
        DatabaseVersion = "MYSQL_5_7",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
        },
        DeletionProtection = true,
    });

    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Ingress = "INGRESS_TRAFFIC_ALL",
        Scaling = new Gcp.CloudRunV2.Inputs.ServiceScalingArgs
        {
            MaxInstanceCount = 2,
        },
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeArgs
                {
                    Name = "cloudsql",
                    CloudSqlInstance = new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeCloudSqlInstanceArgs
                    {
                        Instances = new[]
                        {
                            instance.ConnectionName,
                        },
                    },
                },
            },
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    Envs = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerEnvArgs
                        {
                            Name = "FOO",
                            Value = "bar",
                        },
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerEnvArgs
                        {
                            Name = "SECRET_ENV_VAR",
                            ValueSource = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerEnvValueSourceArgs
                            {
                                SecretKeyRef = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerEnvValueSourceSecretKeyRefArgs
                                {
                                    Secret = secret.SecretId,
                                    Version = "1",
                                },
                            },
                        },
                    },
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerVolumeMountArgs
                        {
                            Name = "cloudsql",
                            MountPath = "/cloudsql",
                        },
                    },
                },
            },
        },
        Traffics = new[]
        {
            new Gcp.CloudRunV2.Inputs.ServiceTrafficArgs
            {
                Type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST",
                Percent = 100,
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret_version_data,
        },
    });

    var project = Gcp.Organizations.GetProject.Invoke();

    var secret_access = new Gcp.SecretManager.SecretIamMember("secret-access", new()
    {
        SecretId = secret.Id,
        Role = "roles/secretmanager.secretAccessor",
        Member = $"serviceAccount:{project.Apply(getProjectResult => getProjectResult.Number)}-compute@developer.gserviceaccount.com",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.Secret;
import com.pulumi.gcp.secretmanager.SecretArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationAutoArgs;
import com.pulumi.gcp.secretmanager.SecretVersion;
import com.pulumi.gcp.secretmanager.SecretVersionArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceScalingArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTrafficArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.secretmanager.SecretIamMember;
import com.pulumi.gcp.secretmanager.SecretIamMemberArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var secret = new Secret("secret", SecretArgs.builder()
            .secretId("secret-1")
            .replication(SecretReplicationArgs.builder()
                .auto(SecretReplicationAutoArgs.builder()
                    .build())
                .build())
            .build());

        var secret_version_data = new SecretVersion("secret-version-data", SecretVersionArgs.builder()
            .secret(secret.name())
            .secretData("secret-data")
            .build());

        var instance = new DatabaseInstance("instance", DatabaseInstanceArgs.builder()
            .name("cloudrun-sql")
            .region("us-central1")
            .databaseVersion("MYSQL_5_7")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-f1-micro")
                .build())
            .deletionProtection(true)
            .build());

        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .ingress("INGRESS_TRAFFIC_ALL")
            .scaling(ServiceScalingArgs.builder()
                .maxInstanceCount(2)
                .build())
            .template(ServiceTemplateArgs.builder()
                .volumes(ServiceTemplateVolumeArgs.builder()
                    .name("cloudsql")
                    .cloudSqlInstance(ServiceTemplateVolumeCloudSqlInstanceArgs.builder()
                        .instances(instance.connectionName())
                        .build())
                    .build())
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .envs(                    
                        ServiceTemplateContainerEnvArgs.builder()
                            .name("FOO")
                            .value("bar")
                            .build(),
                        ServiceTemplateContainerEnvArgs.builder()
                            .name("SECRET_ENV_VAR")
                            .valueSource(ServiceTemplateContainerEnvValueSourceArgs.builder()
                                .secretKeyRef(ServiceTemplateContainerEnvValueSourceSecretKeyRefArgs.builder()
                                    .secret(secret.secretId())
                                    .version("1")
                                    .build())
                                .build())
                            .build())
                    .volumeMounts(ServiceTemplateContainerVolumeMountArgs.builder()
                        .name("cloudsql")
                        .mountPath("/cloudsql")
                        .build())
                    .build())
                .build())
            .traffics(ServiceTrafficArgs.builder()
                .type("TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST")
                .percent(100)
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret_version_data)
                .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var secret_access = new SecretIamMember("secret-access", SecretIamMemberArgs.builder()
            .secretId(secret.id())
            .role("roles/secretmanager.secretAccessor")
            .member(String.format("serviceAccount:%s-compute@developer.gserviceaccount.com", project.number()))
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret)
                .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      ingress: INGRESS_TRAFFIC_ALL
      scaling:
        maxInstanceCount: 2
      template:
        volumes:
          - name: cloudsql
            cloudSqlInstance:
              instances:
                - ${instance.connectionName}
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
            envs:
              - name: FOO
                value: bar
              - name: SECRET_ENV_VAR
                valueSource:
                  secretKeyRef:
                    secret: ${secret.secretId}
                    version: '1'
            volumeMounts:
              - name: cloudsql
                mountPath: /cloudsql
      traffics:
        - type: TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST
          percent: 100
    options:
      dependsOn:
        - ${["secret-version-data"]}
  secret:
    type: gcp:secretmanager:Secret
    properties:
      secretId: secret-1
      replication:
        auto: {}
  secret-version-data:
    type: gcp:secretmanager:SecretVersion
    properties:
      secret: ${secret.name}
      secretData: secret-data
  secret-access:
    type: gcp:secretmanager:SecretIamMember
    properties:
      secretId: ${secret.id}
      role: roles/secretmanager.secretAccessor
      member: serviceAccount:${project.number}-compute@developer.gserviceaccount.com
    options:
      dependsOn:
        - ${secret}
  instance:
    type: gcp:sql:DatabaseInstance
    properties:
      name: cloudrun-sql
      region: us-central1
      databaseVersion: MYSQL_5_7
      settings:
        tier: db-f1-micro
      deletionProtection: true
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The volumes array defines a cloudSqlInstance volume that Cloud Run mounts at the specified path. Your container connects via Unix socket rather than TCP. The envs array shows two patterns: direct values and secrets from Secret Manager via valueSource.secretKeyRef. The service account needs Secret Manager accessor permissions.

Route traffic through VPC Access Connector

Services that need private VPC resources use Serverless VPC Access connectors to route egress traffic.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const customTestNetwork = new gcp.compute.Network("custom_test", {
    name: "run-network",
    autoCreateSubnetworks: false,
});
const customTest = new gcp.compute.Subnetwork("custom_test", {
    name: "run-subnetwork",
    ipCidrRange: "10.2.0.0/28",
    region: "us-central1",
    network: customTestNetwork.id,
});
const connector = new gcp.vpcaccess.Connector("connector", {
    name: "run-vpc",
    subnet: {
        name: customTest.name,
    },
    machineType: "e2-standard-4",
    minInstances: 2,
    maxInstances: 3,
    region: "us-central1",
});
const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
        }],
        vpcAccess: {
            connector: connector.id,
            egress: "ALL_TRAFFIC",
        },
    },
});
import pulumi
import pulumi_gcp as gcp

custom_test_network = gcp.compute.Network("custom_test",
    name="run-network",
    auto_create_subnetworks=False)
custom_test = gcp.compute.Subnetwork("custom_test",
    name="run-subnetwork",
    ip_cidr_range="10.2.0.0/28",
    region="us-central1",
    network=custom_test_network.id)
connector = gcp.vpcaccess.Connector("connector",
    name="run-vpc",
    subnet={
        "name": custom_test.name,
    },
    machine_type="e2-standard-4",
    min_instances=2,
    max_instances=3,
    region="us-central1")
default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
        }],
        "vpc_access": {
            "connector": connector.id,
            "egress": "ALL_TRAFFIC",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/vpcaccess"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		customTestNetwork, err := compute.NewNetwork(ctx, "custom_test", &compute.NetworkArgs{
			Name:                  pulumi.String("run-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		customTest, err := compute.NewSubnetwork(ctx, "custom_test", &compute.SubnetworkArgs{
			Name:        pulumi.String("run-subnetwork"),
			IpCidrRange: pulumi.String("10.2.0.0/28"),
			Region:      pulumi.String("us-central1"),
			Network:     customTestNetwork.ID(),
		})
		if err != nil {
			return err
		}
		connector, err := vpcaccess.NewConnector(ctx, "connector", &vpcaccess.ConnectorArgs{
			Name: pulumi.String("run-vpc"),
			Subnet: &vpcaccess.ConnectorSubnetArgs{
				Name: customTest.Name,
			},
			MachineType:  pulumi.String("e2-standard-4"),
			MinInstances: pulumi.Int(2),
			MaxInstances: pulumi.Int(3),
			Region:       pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Template: &cloudrunv2.ServiceTemplateArgs{
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
					},
				},
				VpcAccess: &cloudrunv2.ServiceTemplateVpcAccessArgs{
					Connector: connector.ID(),
					Egress:    pulumi.String("ALL_TRAFFIC"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var customTestNetwork = new Gcp.Compute.Network("custom_test", new()
    {
        Name = "run-network",
        AutoCreateSubnetworks = false,
    });

    var customTest = new Gcp.Compute.Subnetwork("custom_test", new()
    {
        Name = "run-subnetwork",
        IpCidrRange = "10.2.0.0/28",
        Region = "us-central1",
        Network = customTestNetwork.Id,
    });

    var connector = new Gcp.VpcAccess.Connector("connector", new()
    {
        Name = "run-vpc",
        Subnet = new Gcp.VpcAccess.Inputs.ConnectorSubnetArgs
        {
            Name = customTest.Name,
        },
        MachineType = "e2-standard-4",
        MinInstances = 2,
        MaxInstances = 3,
        Region = "us-central1",
    });

    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                },
            },
            VpcAccess = new Gcp.CloudRunV2.Inputs.ServiceTemplateVpcAccessArgs
            {
                Connector = connector.Id,
                Egress = "ALL_TRAFFIC",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.vpcaccess.Connector;
import com.pulumi.gcp.vpcaccess.ConnectorArgs;
import com.pulumi.gcp.vpcaccess.inputs.ConnectorSubnetArgs;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateVpcAccessArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var customTestNetwork = new Network("customTestNetwork", NetworkArgs.builder()
            .name("run-network")
            .autoCreateSubnetworks(false)
            .build());

        var customTest = new Subnetwork("customTest", SubnetworkArgs.builder()
            .name("run-subnetwork")
            .ipCidrRange("10.2.0.0/28")
            .region("us-central1")
            .network(customTestNetwork.id())
            .build());

        var connector = new Connector("connector", ConnectorArgs.builder()
            .name("run-vpc")
            .subnet(ConnectorSubnetArgs.builder()
                .name(customTest.name())
                .build())
            .machineType("e2-standard-4")
            .minInstances(2)
            .maxInstances(3)
            .region("us-central1")
            .build());

        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .template(ServiceTemplateArgs.builder()
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .build())
                .vpcAccess(ServiceTemplateVpcAccessArgs.builder()
                    .connector(connector.id())
                    .egress("ALL_TRAFFIC")
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
        vpcAccess:
          connector: ${connector.id}
          egress: ALL_TRAFFIC
  connector:
    type: gcp:vpcaccess:Connector
    properties:
      name: run-vpc
      subnet:
        name: ${customTest.name}
      machineType: e2-standard-4
      minInstances: 2
      maxInstances: 3
      region: us-central1
  customTest:
    type: gcp:compute:Subnetwork
    name: custom_test
    properties:
      name: run-subnetwork
      ipCidrRange: 10.2.0.0/28
      region: us-central1
      network: ${customTestNetwork.id}
  customTestNetwork:
    type: gcp:compute:Network
    name: custom_test
    properties:
      name: run-network
      autoCreateSubnetworks: false

The vpcAccess.connector property references a VPC Access Connector that bridges Cloud Run to your VPC. Setting egress to ALL_TRAFFIC routes all outbound requests through the connector, enabling access to private IPs, Cloud SQL private connections, and internal load balancers.

Connect directly to VPC with network interfaces

Direct VPC egress attaches network interfaces to your service, reducing latency for VPC communication.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "GA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
        }],
        vpcAccess: {
            networkInterfaces: [{
                network: "default",
                subnetwork: "default",
                tags: [
                    "tag1",
                    "tag2",
                    "tag3",
                ],
            }],
        },
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    launch_stage="GA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
        }],
        "vpc_access": {
            "network_interfaces": [{
                "network": "default",
                "subnetwork": "default",
                "tags": [
                    "tag1",
                    "tag2",
                    "tag3",
                ],
            }],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("GA"),
			Template: &cloudrunv2.ServiceTemplateArgs{
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
					},
				},
				VpcAccess: &cloudrunv2.ServiceTemplateVpcAccessArgs{
					NetworkInterfaces: cloudrunv2.ServiceTemplateVpcAccessNetworkInterfaceArray{
						&cloudrunv2.ServiceTemplateVpcAccessNetworkInterfaceArgs{
							Network:    pulumi.String("default"),
							Subnetwork: pulumi.String("default"),
							Tags: pulumi.StringArray{
								pulumi.String("tag1"),
								pulumi.String("tag2"),
								pulumi.String("tag3"),
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "GA",
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                },
            },
            VpcAccess = new Gcp.CloudRunV2.Inputs.ServiceTemplateVpcAccessArgs
            {
                NetworkInterfaces = new[]
                {
                    new Gcp.CloudRunV2.Inputs.ServiceTemplateVpcAccessNetworkInterfaceArgs
                    {
                        Network = "default",
                        Subnetwork = "default",
                        Tags = new[]
                        {
                            "tag1",
                            "tag2",
                            "tag3",
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateVpcAccessArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("GA")
            .template(ServiceTemplateArgs.builder()
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .build())
                .vpcAccess(ServiceTemplateVpcAccessArgs.builder()
                    .networkInterfaces(ServiceTemplateVpcAccessNetworkInterfaceArgs.builder()
                        .network("default")
                        .subnetwork("default")
                        .tags(                        
                            "tag1",
                            "tag2",
                            "tag3")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      launchStage: GA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
        vpcAccess:
          networkInterfaces:
            - network: default
              subnetwork: default
              tags:
                - tag1
                - tag2
                - tag3

The networkInterfaces property attaches your service directly to VPC subnets without a connector. This reduces latency and cost for VPC resource access. The tags array applies network tags for firewall rules.

Configure health checks with startup and liveness probes

Production services need health checks to detect container readiness and ongoing health.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
            startupProbe: {
                initialDelaySeconds: 0,
                timeoutSeconds: 1,
                periodSeconds: 3,
                failureThreshold: 1,
                tcpSocket: {
                    port: 8080,
                },
            },
            livenessProbe: {
                httpGet: {
                    path: "/",
                },
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
            "startup_probe": {
                "initial_delay_seconds": 0,
                "timeout_seconds": 1,
                "period_seconds": 3,
                "failure_threshold": 1,
                "tcp_socket": {
                    "port": 8080,
                },
            },
            "liveness_probe": {
                "http_get": {
                    "path": "/",
                },
            },
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Template: &cloudrunv2.ServiceTemplateArgs{
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						StartupProbe: &cloudrunv2.ServiceTemplateContainerStartupProbeArgs{
							InitialDelaySeconds: pulumi.Int(0),
							TimeoutSeconds:      pulumi.Int(1),
							PeriodSeconds:       pulumi.Int(3),
							FailureThreshold:    pulumi.Int(1),
							TcpSocket: &cloudrunv2.ServiceTemplateContainerStartupProbeTcpSocketArgs{
								Port: pulumi.Int(8080),
							},
						},
						LivenessProbe: &cloudrunv2.ServiceTemplateContainerLivenessProbeArgs{
							HttpGet: &cloudrunv2.ServiceTemplateContainerLivenessProbeHttpGetArgs{
								Path: pulumi.String("/"),
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    StartupProbe = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerStartupProbeArgs
                    {
                        InitialDelaySeconds = 0,
                        TimeoutSeconds = 1,
                        PeriodSeconds = 3,
                        FailureThreshold = 1,
                        TcpSocket = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerStartupProbeTcpSocketArgs
                        {
                            Port = 8080,
                        },
                    },
                    LivenessProbe = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerLivenessProbeArgs
                    {
                        HttpGet = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerLivenessProbeHttpGetArgs
                        {
                            Path = "/",
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .template(ServiceTemplateArgs.builder()
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .startupProbe(ServiceTemplateContainerStartupProbeArgs.builder()
                        .initialDelaySeconds(0)
                        .timeoutSeconds(1)
                        .periodSeconds(3)
                        .failureThreshold(1)
                        .tcpSocket(ServiceTemplateContainerStartupProbeTcpSocketArgs.builder()
                            .port(8080)
                            .build())
                        .build())
                    .livenessProbe(ServiceTemplateContainerLivenessProbeArgs.builder()
                        .httpGet(ServiceTemplateContainerLivenessProbeHttpGetArgs.builder()
                            .path("/")
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
            startupProbe:
              initialDelaySeconds: 0
              timeoutSeconds: 1
              periodSeconds: 3
              failureThreshold: 1
              tcpSocket:
                port: 8080
            livenessProbe:
              httpGet:
                path: /

The startupProbe runs during container initialization, using tcpSocket to check port availability. The livenessProbe monitors running containers with httpGet requests. Cloud Run replaces containers that fail liveness checks. The periodSeconds and failureThreshold properties control check frequency and tolerance.

Run multiple containers with shared volumes

Sidecar patterns can run multiple containers in a single service, sharing volumes and coordinating startup.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    ingress: "INGRESS_TRAFFIC_ALL",
    template: {
        containers: [
            {
                name: "hello-1",
                ports: {
                    containerPort: 8080,
                },
                image: "us-docker.pkg.dev/cloudrun/container/hello",
                dependsOns: ["hello-2"],
                volumeMounts: [{
                    name: "empty-dir-volume",
                    mountPath: "/mnt",
                }],
            },
            {
                name: "hello-2",
                image: "us-docker.pkg.dev/cloudrun/container/hello",
                envs: [{
                    name: "PORT",
                    value: "8081",
                }],
                startupProbe: {
                    httpGet: {
                        port: 8081,
                    },
                },
            },
        ],
        volumes: [{
            name: "empty-dir-volume",
            emptyDir: {
                medium: "MEMORY",
                sizeLimit: "256Mi",
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    ingress="INGRESS_TRAFFIC_ALL",
    template={
        "containers": [
            {
                "name": "hello-1",
                "ports": {
                    "container_port": 8080,
                },
                "image": "us-docker.pkg.dev/cloudrun/container/hello",
                "depends_ons": ["hello-2"],
                "volume_mounts": [{
                    "name": "empty-dir-volume",
                    "mount_path": "/mnt",
                }],
            },
            {
                "name": "hello-2",
                "image": "us-docker.pkg.dev/cloudrun/container/hello",
                "envs": [{
                    "name": "PORT",
                    "value": "8081",
                }],
                "startup_probe": {
                    "http_get": {
                        "port": 8081,
                    },
                },
            },
        ],
        "volumes": [{
            "name": "empty-dir-volume",
            "empty_dir": {
                "medium": "MEMORY",
                "size_limit": "256Mi",
            },
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Ingress:            pulumi.String("INGRESS_TRAFFIC_ALL"),
			Template: &cloudrunv2.ServiceTemplateArgs{
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Name: pulumi.String("hello-1"),
						Ports: &cloudrunv2.ServiceTemplateContainerPortsArgs{
							ContainerPort: pulumi.Int(8080),
						},
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						DependsOns: pulumi.StringArray{
							pulumi.String("hello-2"),
						},
						VolumeMounts: cloudrunv2.ServiceTemplateContainerVolumeMountArray{
							&cloudrunv2.ServiceTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("empty-dir-volume"),
								MountPath: pulumi.String("/mnt"),
							},
						},
					},
					&cloudrunv2.ServiceTemplateContainerArgs{
						Name:  pulumi.String("hello-2"),
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						Envs: cloudrunv2.ServiceTemplateContainerEnvArray{
							&cloudrunv2.ServiceTemplateContainerEnvArgs{
								Name:  pulumi.String("PORT"),
								Value: pulumi.String("8081"),
							},
						},
						StartupProbe: &cloudrunv2.ServiceTemplateContainerStartupProbeArgs{
							HttpGet: &cloudrunv2.ServiceTemplateContainerStartupProbeHttpGetArgs{
								Port: pulumi.Int(8081),
							},
						},
					},
				},
				Volumes: cloudrunv2.ServiceTemplateVolumeArray{
					&cloudrunv2.ServiceTemplateVolumeArgs{
						Name: pulumi.String("empty-dir-volume"),
						EmptyDir: &cloudrunv2.ServiceTemplateVolumeEmptyDirArgs{
							Medium:    pulumi.String("MEMORY"),
							SizeLimit: pulumi.String("256Mi"),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Ingress = "INGRESS_TRAFFIC_ALL",
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Name = "hello-1",
                    Ports = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerPortsArgs
                    {
                        ContainerPort = 8080,
                    },
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    DependsOns = new[]
                    {
                        "hello-2",
                    },
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerVolumeMountArgs
                        {
                            Name = "empty-dir-volume",
                            MountPath = "/mnt",
                        },
                    },
                },
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Name = "hello-2",
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    Envs = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerEnvArgs
                        {
                            Name = "PORT",
                            Value = "8081",
                        },
                    },
                    StartupProbe = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerStartupProbeArgs
                    {
                        HttpGet = new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerStartupProbeHttpGetArgs
                        {
                            Port = 8081,
                        },
                    },
                },
            },
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeArgs
                {
                    Name = "empty-dir-volume",
                    EmptyDir = new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeEmptyDirArgs
                    {
                        Medium = "MEMORY",
                        SizeLimit = "256Mi",
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .ingress("INGRESS_TRAFFIC_ALL")
            .template(ServiceTemplateArgs.builder()
                .containers(                
                    ServiceTemplateContainerArgs.builder()
                        .name("hello-1")
                        .ports(ServiceTemplateContainerPortsArgs.builder()
                            .containerPort(8080)
                            .build())
                        .image("us-docker.pkg.dev/cloudrun/container/hello")
                        .dependsOns("hello-2")
                        .volumeMounts(ServiceTemplateContainerVolumeMountArgs.builder()
                            .name("empty-dir-volume")
                            .mountPath("/mnt")
                            .build())
                        .build(),
                    ServiceTemplateContainerArgs.builder()
                        .name("hello-2")
                        .image("us-docker.pkg.dev/cloudrun/container/hello")
                        .envs(ServiceTemplateContainerEnvArgs.builder()
                            .name("PORT")
                            .value("8081")
                            .build())
                        .startupProbe(ServiceTemplateContainerStartupProbeArgs.builder()
                            .httpGet(ServiceTemplateContainerStartupProbeHttpGetArgs.builder()
                                .port(8081)
                                .build())
                            .build())
                        .build())
                .volumes(ServiceTemplateVolumeArgs.builder()
                    .name("empty-dir-volume")
                    .emptyDir(ServiceTemplateVolumeEmptyDirArgs.builder()
                        .medium("MEMORY")
                        .sizeLimit("256Mi")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      ingress: INGRESS_TRAFFIC_ALL
      template:
        containers:
          - name: hello-1
            ports:
              containerPort: 8080
            image: us-docker.pkg.dev/cloudrun/container/hello
            dependsOns:
              - hello-2
            volumeMounts:
              - name: empty-dir-volume
                mountPath: /mnt
          - name: hello-2
            image: us-docker.pkg.dev/cloudrun/container/hello
            envs:
              - name: PORT
                value: '8081'
            startupProbe:
              httpGet:
                port: 8081
        volumes:
          - name: empty-dir-volume
            emptyDir:
              medium: MEMORY
              sizeLimit: 256Mi

The containers array defines multiple containers with distinct names. The dependsOns property controls startup order, ensuring hello-2 starts before hello-1. The emptyDir volume provides shared memory-backed storage. Each container mounts volumes at different paths via volumeMounts.

Mount secrets as files in containers

Applications that read configuration from files can mount Secret Manager secrets as volumes.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const secret = new gcp.secretmanager.Secret("secret", {
    secretId: "secret-1",
    replication: {
        auto: {},
    },
});
const secret_version_data = new gcp.secretmanager.SecretVersion("secret-version-data", {
    secret: secret.name,
    secretData: "secret-data",
});
const _default = new gcp.cloudrunv2.Service("default", {
    name: "cloudrun-service",
    location: "us-central1",
    deletionProtection: false,
    ingress: "INGRESS_TRAFFIC_ALL",
    template: {
        volumes: [{
            name: "a-volume",
            secret: {
                secret: secret.secretId,
                defaultMode: 292,
                items: [{
                    version: "1",
                    path: "my-secret",
                }],
            },
        }],
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/hello",
            volumeMounts: [{
                name: "a-volume",
                mountPath: "/secrets",
            }],
        }],
    },
}, {
    dependsOn: [secret_version_data],
});
const project = gcp.organizations.getProject({});
const secret_access = new gcp.secretmanager.SecretIamMember("secret-access", {
    secretId: secret.id,
    role: "roles/secretmanager.secretAccessor",
    member: project.then(project => `serviceAccount:${project.number}-compute@developer.gserviceaccount.com`),
}, {
    dependsOn: [secret],
});
import pulumi
import pulumi_gcp as gcp

secret = gcp.secretmanager.Secret("secret",
    secret_id="secret-1",
    replication={
        "auto": {},
    })
secret_version_data = gcp.secretmanager.SecretVersion("secret-version-data",
    secret=secret.name,
    secret_data="secret-data")
default = gcp.cloudrunv2.Service("default",
    name="cloudrun-service",
    location="us-central1",
    deletion_protection=False,
    ingress="INGRESS_TRAFFIC_ALL",
    template={
        "volumes": [{
            "name": "a-volume",
            "secret": {
                "secret": secret.secret_id,
                "default_mode": 292,
                "items": [{
                    "version": "1",
                    "path": "my-secret",
                }],
            },
        }],
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/hello",
            "volume_mounts": [{
                "name": "a-volume",
                "mount_path": "/secrets",
            }],
        }],
    },
    opts = pulumi.ResourceOptions(depends_on=[secret_version_data]))
project = gcp.organizations.get_project()
secret_access = gcp.secretmanager.SecretIamMember("secret-access",
    secret_id=secret.id,
    role="roles/secretmanager.secretAccessor",
    member=f"serviceAccount:{project.number}-compute@developer.gserviceaccount.com",
    opts = pulumi.ResourceOptions(depends_on=[secret]))
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		secret, err := secretmanager.NewSecret(ctx, "secret", &secretmanager.SecretArgs{
			SecretId: pulumi.String("secret-1"),
			Replication: &secretmanager.SecretReplicationArgs{
				Auto: &secretmanager.SecretReplicationAutoArgs{},
			},
		})
		if err != nil {
			return err
		}
		secret_version_data, err := secretmanager.NewSecretVersion(ctx, "secret-version-data", &secretmanager.SecretVersionArgs{
			Secret:     secret.Name,
			SecretData: pulumi.String("secret-data"),
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewService(ctx, "default", &cloudrunv2.ServiceArgs{
			Name:               pulumi.String("cloudrun-service"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			Ingress:            pulumi.String("INGRESS_TRAFFIC_ALL"),
			Template: &cloudrunv2.ServiceTemplateArgs{
				Volumes: cloudrunv2.ServiceTemplateVolumeArray{
					&cloudrunv2.ServiceTemplateVolumeArgs{
						Name: pulumi.String("a-volume"),
						Secret: &cloudrunv2.ServiceTemplateVolumeSecretArgs{
							Secret:      secret.SecretId,
							DefaultMode: pulumi.Int(292),
							Items: cloudrunv2.ServiceTemplateVolumeSecretItemArray{
								&cloudrunv2.ServiceTemplateVolumeSecretItemArgs{
									Version: pulumi.String("1"),
									Path:    pulumi.String("my-secret"),
								},
							},
						},
					},
				},
				Containers: cloudrunv2.ServiceTemplateContainerArray{
					&cloudrunv2.ServiceTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/hello"),
						VolumeMounts: cloudrunv2.ServiceTemplateContainerVolumeMountArray{
							&cloudrunv2.ServiceTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("a-volume"),
								MountPath: pulumi.String("/secrets"),
							},
						},
					},
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			secret_version_data,
		}))
		if err != nil {
			return err
		}
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = secretmanager.NewSecretIamMember(ctx, "secret-access", &secretmanager.SecretIamMemberArgs{
			SecretId: secret.ID(),
			Role:     pulumi.String("roles/secretmanager.secretAccessor"),
			Member:   pulumi.Sprintf("serviceAccount:%v-compute@developer.gserviceaccount.com", project.Number),
		}, pulumi.DependsOn([]pulumi.Resource{
			secret,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var secret = new Gcp.SecretManager.Secret("secret", new()
    {
        SecretId = "secret-1",
        Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
        {
            Auto = null,
        },
    });

    var secret_version_data = new Gcp.SecretManager.SecretVersion("secret-version-data", new()
    {
        Secret = secret.Name,
        SecretData = "secret-data",
    });

    var @default = new Gcp.CloudRunV2.Service("default", new()
    {
        Name = "cloudrun-service",
        Location = "us-central1",
        DeletionProtection = false,
        Ingress = "INGRESS_TRAFFIC_ALL",
        Template = new Gcp.CloudRunV2.Inputs.ServiceTemplateArgs
        {
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeArgs
                {
                    Name = "a-volume",
                    Secret = new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeSecretArgs
                    {
                        Secret = secret.SecretId,
                        DefaultMode = 292,
                        Items = new[]
                        {
                            new Gcp.CloudRunV2.Inputs.ServiceTemplateVolumeSecretItemArgs
                            {
                                Version = "1",
                                Path = "my-secret",
                            },
                        },
                    },
                },
            },
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/hello",
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.ServiceTemplateContainerVolumeMountArgs
                        {
                            Name = "a-volume",
                            MountPath = "/secrets",
                        },
                    },
                },
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret_version_data,
        },
    });

    var project = Gcp.Organizations.GetProject.Invoke();

    var secret_access = new Gcp.SecretManager.SecretIamMember("secret-access", new()
    {
        SecretId = secret.Id,
        Role = "roles/secretmanager.secretAccessor",
        Member = $"serviceAccount:{project.Apply(getProjectResult => getProjectResult.Number)}-compute@developer.gserviceaccount.com",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.Secret;
import com.pulumi.gcp.secretmanager.SecretArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationAutoArgs;
import com.pulumi.gcp.secretmanager.SecretVersion;
import com.pulumi.gcp.secretmanager.SecretVersionArgs;
import com.pulumi.gcp.cloudrunv2.Service;
import com.pulumi.gcp.cloudrunv2.ServiceArgs;
import com.pulumi.gcp.cloudrunv2.inputs.ServiceTemplateArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.secretmanager.SecretIamMember;
import com.pulumi.gcp.secretmanager.SecretIamMemberArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var secret = new Secret("secret", SecretArgs.builder()
            .secretId("secret-1")
            .replication(SecretReplicationArgs.builder()
                .auto(SecretReplicationAutoArgs.builder()
                    .build())
                .build())
            .build());

        var secret_version_data = new SecretVersion("secret-version-data", SecretVersionArgs.builder()
            .secret(secret.name())
            .secretData("secret-data")
            .build());

        var default_ = new Service("default", ServiceArgs.builder()
            .name("cloudrun-service")
            .location("us-central1")
            .deletionProtection(false)
            .ingress("INGRESS_TRAFFIC_ALL")
            .template(ServiceTemplateArgs.builder()
                .volumes(ServiceTemplateVolumeArgs.builder()
                    .name("a-volume")
                    .secret(ServiceTemplateVolumeSecretArgs.builder()
                        .secret(secret.secretId())
                        .defaultMode(292)
                        .items(ServiceTemplateVolumeSecretItemArgs.builder()
                            .version("1")
                            .path("my-secret")
                            .build())
                        .build())
                    .build())
                .containers(ServiceTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/hello")
                    .volumeMounts(ServiceTemplateContainerVolumeMountArgs.builder()
                        .name("a-volume")
                        .mountPath("/secrets")
                        .build())
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret_version_data)
                .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var secret_access = new SecretIamMember("secret-access", SecretIamMemberArgs.builder()
            .secretId(secret.id())
            .role("roles/secretmanager.secretAccessor")
            .member(String.format("serviceAccount:%s-compute@developer.gserviceaccount.com", project.number()))
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret)
                .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:Service
    properties:
      name: cloudrun-service
      location: us-central1
      deletionProtection: false
      ingress: INGRESS_TRAFFIC_ALL
      template:
        volumes:
          - name: a-volume
            secret:
              secret: ${secret.secretId}
              defaultMode: 292
              items:
                - version: '1'
                  path: my-secret
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/hello
            volumeMounts:
              - name: a-volume
                mountPath: /secrets
    options:
      dependsOn:
        - ${["secret-version-data"]}
  secret:
    type: gcp:secretmanager:Secret
    properties:
      secretId: secret-1
      replication:
        auto: {}
  secret-version-data:
    type: gcp:secretmanager:SecretVersion
    properties:
      secret: ${secret.name}
      secretData: secret-data
  secret-access:
    type: gcp:secretmanager:SecretIamMember
    properties:
      secretId: ${secret.id}
      role: roles/secretmanager.secretAccessor
      member: serviceAccount:${project.number}-compute@developer.gserviceaccount.com
    options:
      dependsOn:
        - ${secret}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The volumes.secret block mounts a Secret Manager secret at the specified path. The items array maps secret versions to file paths within the mount. Your container reads the secret from /secrets/my-secret. The defaultMode sets file permissions (292 is octal 0444, read-only).

Beyond these examples

These snippets focus on specific service-level features: container deployment and resource limits, VPC networking (connectors and direct interfaces), volume mounts (Cloud SQL, secrets, GCS, NFS, emptyDir), and health probes and multi-container sidecars. They’re intentionally minimal rather than full application deployments.

The examples may reference pre-existing infrastructure such as VPC networks, subnets, and VPC Access Connectors, Cloud SQL instances and Secret Manager secrets, and IAM service accounts with appropriate permissions. They focus on configuring the service rather than provisioning everything around it.

To keep things focused, common service patterns are omitted, including:

  • Traffic splitting and revision management (traffics property)
  • Binary Authorization and build configuration
  • Service mesh integration and IAP authentication
  • Custom audiences and invoker IAM controls
  • GCS and NFS volume mounts
  • GPU configuration and node selectors

These omissions are intentional: the goal is to illustrate how each service feature is wired, not provide drop-in application modules. See the Cloud Run Service resource reference for all available configuration options.

Let's deploy GCP Cloud Run Services

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
What properties can't I change after creating a Cloud Run service?
The location, name, and project properties are immutable and cannot be changed after service creation.
Why don't my annotations and labels show all values on the resource?
The annotations and labels fields are non-authoritative and only manage values present in your configuration. To access all annotations and labels on the resource, use the effectiveAnnotations and effectiveLabels output fields.
What does the reconciling field mean?
The reconciling output field indicates whether Cloud Run is asynchronously performing steps to bring the service to its desired state. When true, fields like observedGeneration, latestReadyRevision, and uri may have transient values. Once reconciliation completes, these fields will match the intended state or show error information in terminalCondition.
Networking & VPC
What's the difference between VPC connector and direct VPC access?
VPC connector uses vpcAccess.connector with a connector ID and egress setting. Direct VPC access uses vpcAccess.networkInterfaces with network, subnetwork, and optional tags. Direct VPC provides more granular control over network configuration.
What ingress options are available for Cloud Run services?
Three ingress options are available: INGRESS_TRAFFIC_ALL (public access), INGRESS_TRAFFIC_INTERNAL_ONLY (VPC internal only), and INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER (internal load balancer only).
Dependencies & Timing
Why do I need to wait after creating a service mesh before deploying my service?
Service mesh integration requires the mesh to be fully ready before creating the service. Use a 1-minute delay (e.g., time.Sleep with createDuration: "1m") after mesh creation and add it as a dependency.
How do I grant my Cloud Run service access to secrets?
Grant the compute service account roles/secretmanager.secretAccessor role using gcp.secretmanager.SecretIamMember. Use dependsOn to ensure the secret version exists before creating the service.
Storage & Volumes
How do I mount a GCS bucket in my Cloud Run service?
Set template.executionEnvironment to EXECUTION_ENVIRONMENT_GEN2, create a volume with gcs configuration containing the bucket name and readOnly setting, then mount it using volumeMounts in your container.
How do I mount an NFS/Filestore volume in my Cloud Run service?
Set template.executionEnvironment to EXECUTION_ENVIRONMENT_GEN2, configure vpcAccess.networkInterfaces for VPC connectivity, create a volume with nfs configuration (server IP and path), and mount it in your container.
How do I connect my Cloud Run service to a Cloud SQL instance?
Create a volume with cloudSqlInstance containing the instance connection name, mount it in your container using volumeMounts, and use dependsOn to ensure dependencies are created first.
Advanced Features
How do I configure GPU support for my Cloud Run service?
Set container resource limits including nvidia.com/gpu (e.g., "1"), configure template.nodeSelector.accelerator with the GPU type (e.g., nvidia-l4), and optionally set gpuZonalRedundancyDisabled to true.
How do I run multiple containers in a single Cloud Run service?
Define multiple containers in template.containers. Use the dependsOns field to specify startup order, and share data between containers using emptyDir volumes with medium and sizeLimit settings.
How do I enable IAP for my Cloud Run service?
Set iapEnabled to true and launchStage to BETA, as IAP is a preview feature.
How do I disable IAM permission checks for my Cloud Run service?
Set invokerIamDisabled to true. The service URL will not perform IAM checks when invoked.
Traffic & Deployment
What happens if I don't specify traffic distribution?
If traffics is empty or not provided, Cloud Run defaults to 100% traffic to the latest Ready Revision.
What launch stages are available and which should I use?
Available launch stages are ALPHA, BETA, and GA. If not specified, GA is assumed. Set the launch stage to a preview stage (ALPHA or BETA) to use preview features in that stage.

Using a different cloud?

Explore containers guides for other cloud providers: