The gcp:artifactregistry/repository:Repository resource, part of the Pulumi GCP provider, defines an Artifact Registry repository: its format, location, mode, and access configuration. This guide focuses on four capabilities: regional and multi-region deployment, virtual and remote repository modes, cleanup policies and encryption, and authentication for external registries.
Repositories may reference KMS keys, Secret Manager secrets, or upstream repositories that must exist separately. The examples are intentionally small. Combine them with your own IAM policies, networking, and access controls.
Create a regional Docker repository with metadata
Most deployments start with a standard repository in a specific region, storing container images for CI/CD pipelines.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example docker repository",
format: "DOCKER",
});
import pulumi
import pulumi_gcp as gcp
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example docker repository",
format="DOCKER")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example docker repository"),
Format: pulumi.String("DOCKER"),
})
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 my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example docker repository",
Format = "DOCKER",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
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 my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example docker repository")
.format("DOCKER")
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example docker repository
format: DOCKER
The location property places the repository in a specific region. The repositoryId sets the repository name (must be unique within the location). The format property determines what artifact types the repository accepts (DOCKER, MAVEN, NPM, PYTHON, APT, YUM, or others). The description adds human-readable metadata.
Deploy a multi-region repository for global access
Teams with globally distributed infrastructure need repositories that replicate across regions to reduce latency.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
repositoryId: "my-repository",
description: "example docker repository",
location: "us",
format: "DOCKER",
});
import pulumi
import pulumi_gcp as gcp
my_repo = gcp.artifactregistry.Repository("my-repo",
repository_id="my-repository",
description="example docker repository",
location="us",
format="DOCKER")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example docker repository"),
Location: pulumi.String("us"),
Format: pulumi.String("DOCKER"),
})
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 my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
RepositoryId = "my-repository",
Description = "example docker repository",
Location = "us",
Format = "DOCKER",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
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 my_repo = new Repository("my-repo", RepositoryArgs.builder()
.repositoryId("my-repository")
.description("example docker repository")
.location("us")
.format("DOCKER")
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
repositoryId: my-repository
description: example docker repository
location: us
format: DOCKER
Setting location to “us”, “europe”, or “asia” creates a multi-region repository that replicates artifacts across multiple regions within that geography. This improves pull performance for globally distributed workloads but increases storage costs.
Enforce immutable tags for Docker images
Production environments often require immutable tags to prevent accidental overwrites of deployed versions.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example docker repository",
format: "DOCKER",
dockerConfig: {
immutableTags: true,
},
});
import pulumi
import pulumi_gcp as gcp
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example docker repository",
format="DOCKER",
docker_config={
"immutable_tags": True,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example docker repository"),
Format: pulumi.String("DOCKER"),
DockerConfig: &artifactregistry.RepositoryDockerConfigArgs{
ImmutableTags: pulumi.Bool(true),
},
})
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 my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example docker repository",
Format = "DOCKER",
DockerConfig = new Gcp.ArtifactRegistry.Inputs.RepositoryDockerConfigArgs
{
ImmutableTags = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryDockerConfigArgs;
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 my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example docker repository")
.format("DOCKER")
.dockerConfig(RepositoryDockerConfigArgs.builder()
.immutableTags(true)
.build())
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example docker repository
format: DOCKER
dockerConfig:
immutableTags: true
The dockerConfig block contains Docker-specific settings. Setting immutableTags to true prevents tag overwrites; once a tag is pushed, it cannot be changed or deleted. This protects production deployments from accidental image updates.
Encrypt repository contents with customer-managed keys
Organizations with strict compliance requirements need to control encryption keys rather than relying on Google-managed encryption.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = gcp.organizations.getProject({});
const cryptoKey = new gcp.kms.CryptoKeyIAMMember("crypto_key", {
cryptoKeyId: "kms-key",
role: "roles/cloudkms.cryptoKeyEncrypterDecrypter",
member: project.then(project => `serviceAccount:service-${project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com`),
});
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example docker repository with cmek",
format: "DOCKER",
kmsKeyName: "kms-key",
}, {
dependsOn: [cryptoKey],
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.get_project()
crypto_key = gcp.kms.CryptoKeyIAMMember("crypto_key",
crypto_key_id="kms-key",
role="roles/cloudkms.cryptoKeyEncrypterDecrypter",
member=f"serviceAccount:service-{project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com")
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example docker repository with cmek",
format="DOCKER",
kms_key_name="kms-key",
opts = pulumi.ResourceOptions(depends_on=[crypto_key]))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/kms"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
cryptoKey, err := kms.NewCryptoKeyIAMMember(ctx, "crypto_key", &kms.CryptoKeyIAMMemberArgs{
CryptoKeyId: pulumi.String("kms-key"),
Role: pulumi.String("roles/cloudkms.cryptoKeyEncrypterDecrypter"),
Member: pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-artifactregistry.iam.gserviceaccount.com", project.Number),
})
if err != nil {
return err
}
_, err = artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example docker repository with cmek"),
Format: pulumi.String("DOCKER"),
KmsKeyName: pulumi.String("kms-key"),
}, pulumi.DependsOn([]pulumi.Resource{
cryptoKey,
}))
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 project = Gcp.Organizations.GetProject.Invoke();
var cryptoKey = new Gcp.Kms.CryptoKeyIAMMember("crypto_key", new()
{
CryptoKeyId = "kms-key",
Role = "roles/cloudkms.cryptoKeyEncrypterDecrypter",
Member = $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-artifactregistry.iam.gserviceaccount.com",
});
var my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example docker repository with cmek",
Format = "DOCKER",
KmsKeyName = "kms-key",
}, new CustomResourceOptions
{
DependsOn =
{
cryptoKey,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.kms.CryptoKeyIAMMember;
import com.pulumi.gcp.kms.CryptoKeyIAMMemberArgs;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
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) {
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var cryptoKey = new CryptoKeyIAMMember("cryptoKey", CryptoKeyIAMMemberArgs.builder()
.cryptoKeyId("kms-key")
.role("roles/cloudkms.cryptoKeyEncrypterDecrypter")
.member(String.format("serviceAccount:service-%s@gcp-sa-artifactregistry.iam.gserviceaccount.com", project.number()))
.build());
var my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example docker repository with cmek")
.format("DOCKER")
.kmsKeyName("kms-key")
.build(), CustomResourceOptions.builder()
.dependsOn(cryptoKey)
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example docker repository with cmek
format: DOCKER
kmsKeyName: kms-key
options:
dependsOn:
- ${cryptoKey}
cryptoKey:
type: gcp:kms:CryptoKeyIAMMember
name: crypto_key
properties:
cryptoKeyId: kms-key
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
member: serviceAccount:service-${project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The kmsKeyName property references a Cloud KMS key for encrypting repository contents. The CryptoKeyIAMMember grants the Artifact Registry service account permission to use the key. The dependsOn ensures the IAM binding exists before creating the repository.
Aggregate multiple repositories with priority routing
Virtual repositories act as a single endpoint that routes requests to multiple upstream repositories based on priority.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo_upstream_1 = new gcp.artifactregistry.Repository("my-repo-upstream-1", {
location: "us-central1",
repositoryId: "my-repository-upstream-1",
description: "example docker repository (upstream source) 1",
format: "DOCKER",
});
const my_repo_upstream_2 = new gcp.artifactregistry.Repository("my-repo-upstream-2", {
location: "us-central1",
repositoryId: "my-repository-upstream-2",
description: "example docker repository (upstream source) 2",
format: "DOCKER",
});
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example virtual docker repository",
format: "DOCKER",
mode: "VIRTUAL_REPOSITORY",
virtualRepositoryConfig: {
upstreamPolicies: [
{
id: "my-repository-upstream-1",
repository: my_repo_upstream_1.id,
priority: 20,
},
{
id: "my-repository-upstream-2",
repository: my_repo_upstream_2.id,
priority: 10,
},
],
},
});
import pulumi
import pulumi_gcp as gcp
my_repo_upstream_1 = gcp.artifactregistry.Repository("my-repo-upstream-1",
location="us-central1",
repository_id="my-repository-upstream-1",
description="example docker repository (upstream source) 1",
format="DOCKER")
my_repo_upstream_2 = gcp.artifactregistry.Repository("my-repo-upstream-2",
location="us-central1",
repository_id="my-repository-upstream-2",
description="example docker repository (upstream source) 2",
format="DOCKER")
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example virtual docker repository",
format="DOCKER",
mode="VIRTUAL_REPOSITORY",
virtual_repository_config={
"upstream_policies": [
{
"id": "my-repository-upstream-1",
"repository": my_repo_upstream_1.id,
"priority": 20,
},
{
"id": "my-repository-upstream-2",
"repository": my_repo_upstream_2.id,
"priority": 10,
},
],
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
my_repo_upstream_1, err := artifactregistry.NewRepository(ctx, "my-repo-upstream-1", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository-upstream-1"),
Description: pulumi.String("example docker repository (upstream source) 1"),
Format: pulumi.String("DOCKER"),
})
if err != nil {
return err
}
my_repo_upstream_2, err := artifactregistry.NewRepository(ctx, "my-repo-upstream-2", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository-upstream-2"),
Description: pulumi.String("example docker repository (upstream source) 2"),
Format: pulumi.String("DOCKER"),
})
if err != nil {
return err
}
_, err = artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example virtual docker repository"),
Format: pulumi.String("DOCKER"),
Mode: pulumi.String("VIRTUAL_REPOSITORY"),
VirtualRepositoryConfig: &artifactregistry.RepositoryVirtualRepositoryConfigArgs{
UpstreamPolicies: artifactregistry.RepositoryVirtualRepositoryConfigUpstreamPolicyArray{
&artifactregistry.RepositoryVirtualRepositoryConfigUpstreamPolicyArgs{
Id: pulumi.String("my-repository-upstream-1"),
Repository: my_repo_upstream_1.ID(),
Priority: pulumi.Int(20),
},
&artifactregistry.RepositoryVirtualRepositoryConfigUpstreamPolicyArgs{
Id: pulumi.String("my-repository-upstream-2"),
Repository: my_repo_upstream_2.ID(),
Priority: pulumi.Int(10),
},
},
},
})
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 my_repo_upstream_1 = new Gcp.ArtifactRegistry.Repository("my-repo-upstream-1", new()
{
Location = "us-central1",
RepositoryId = "my-repository-upstream-1",
Description = "example docker repository (upstream source) 1",
Format = "DOCKER",
});
var my_repo_upstream_2 = new Gcp.ArtifactRegistry.Repository("my-repo-upstream-2", new()
{
Location = "us-central1",
RepositoryId = "my-repository-upstream-2",
Description = "example docker repository (upstream source) 2",
Format = "DOCKER",
});
var my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example virtual docker repository",
Format = "DOCKER",
Mode = "VIRTUAL_REPOSITORY",
VirtualRepositoryConfig = new Gcp.ArtifactRegistry.Inputs.RepositoryVirtualRepositoryConfigArgs
{
UpstreamPolicies = new[]
{
new Gcp.ArtifactRegistry.Inputs.RepositoryVirtualRepositoryConfigUpstreamPolicyArgs
{
Id = "my-repository-upstream-1",
Repository = my_repo_upstream_1.Id,
Priority = 20,
},
new Gcp.ArtifactRegistry.Inputs.RepositoryVirtualRepositoryConfigUpstreamPolicyArgs
{
Id = "my-repository-upstream-2",
Repository = my_repo_upstream_2.Id,
Priority = 10,
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryVirtualRepositoryConfigArgs;
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 my_repo_upstream_1 = new Repository("my-repo-upstream-1", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository-upstream-1")
.description("example docker repository (upstream source) 1")
.format("DOCKER")
.build());
var my_repo_upstream_2 = new Repository("my-repo-upstream-2", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository-upstream-2")
.description("example docker repository (upstream source) 2")
.format("DOCKER")
.build());
var my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example virtual docker repository")
.format("DOCKER")
.mode("VIRTUAL_REPOSITORY")
.virtualRepositoryConfig(RepositoryVirtualRepositoryConfigArgs.builder()
.upstreamPolicies(
RepositoryVirtualRepositoryConfigUpstreamPolicyArgs.builder()
.id("my-repository-upstream-1")
.repository(my_repo_upstream_1.id())
.priority(20)
.build(),
RepositoryVirtualRepositoryConfigUpstreamPolicyArgs.builder()
.id("my-repository-upstream-2")
.repository(my_repo_upstream_2.id())
.priority(10)
.build())
.build())
.build());
}
}
resources:
my-repo-upstream-1:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository-upstream-1
description: example docker repository (upstream source) 1
format: DOCKER
my-repo-upstream-2:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository-upstream-2
description: example docker repository (upstream source) 2
format: DOCKER
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example virtual docker repository
format: DOCKER
mode: VIRTUAL_REPOSITORY
virtualRepositoryConfig:
upstreamPolicies:
- id: my-repository-upstream-1
repository: ${["my-repo-upstream-1"].id}
priority: 20
- id: my-repository-upstream-2
repository: ${["my-repo-upstream-2"].id}
priority: 10
Setting mode to “VIRTUAL_REPOSITORY” creates a routing layer. The virtualRepositoryConfig defines upstreamPolicies that list source repositories and their priorities. Lower priority numbers are checked first; if an artifact isn’t found, the next priority is tried.
Cache Docker Hub images as a pull-through proxy
Remote repositories cache artifacts from external registries, reducing external bandwidth and improving pull performance.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example remote docker repository",
format: "DOCKER",
mode: "REMOTE_REPOSITORY",
remoteRepositoryConfig: {
description: "docker hub",
dockerRepository: {
publicRepository: "DOCKER_HUB",
},
},
});
import pulumi
import pulumi_gcp as gcp
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example remote docker repository",
format="DOCKER",
mode="REMOTE_REPOSITORY",
remote_repository_config={
"description": "docker hub",
"docker_repository": {
"public_repository": "DOCKER_HUB",
},
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example remote docker repository"),
Format: pulumi.String("DOCKER"),
Mode: pulumi.String("REMOTE_REPOSITORY"),
RemoteRepositoryConfig: &artifactregistry.RepositoryRemoteRepositoryConfigArgs{
Description: pulumi.String("docker hub"),
DockerRepository: &artifactregistry.RepositoryRemoteRepositoryConfigDockerRepositoryArgs{
PublicRepository: pulumi.String("DOCKER_HUB"),
},
},
})
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 my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example remote docker repository",
Format = "DOCKER",
Mode = "REMOTE_REPOSITORY",
RemoteRepositoryConfig = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigArgs
{
Description = "docker hub",
DockerRepository = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigDockerRepositoryArgs
{
PublicRepository = "DOCKER_HUB",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigDockerRepositoryArgs;
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 my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example remote docker repository")
.format("DOCKER")
.mode("REMOTE_REPOSITORY")
.remoteRepositoryConfig(RepositoryRemoteRepositoryConfigArgs.builder()
.description("docker hub")
.dockerRepository(RepositoryRemoteRepositoryConfigDockerRepositoryArgs.builder()
.publicRepository("DOCKER_HUB")
.build())
.build())
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example remote docker repository
format: DOCKER
mode: REMOTE_REPOSITORY
remoteRepositoryConfig:
description: docker hub
dockerRepository:
publicRepository: DOCKER_HUB
Setting mode to “REMOTE_REPOSITORY” creates a caching proxy. The remoteRepositoryConfig specifies the upstream source. Setting publicRepository to “DOCKER_HUB” configures Docker Hub as the upstream; pulls are cached locally after the first request.
Automate artifact deletion with cleanup policies
Repositories accumulate old versions and untagged images over time. Cleanup policies automatically delete artifacts based on rules.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "my-repository",
description: "example docker repository with cleanup policies",
format: "DOCKER",
cleanupPolicyDryRun: false,
cleanupPolicies: [
{
id: "delete-untagged",
action: "DELETE",
condition: {
tagState: "UNTAGGED",
},
},
{
id: "keep-new-untagged",
action: "KEEP",
condition: {
tagState: "UNTAGGED",
newerThan: "7d",
},
},
{
id: "delete-prerelease",
action: "DELETE",
condition: {
tagState: "TAGGED",
tagPrefixes: [
"alpha",
"v0",
],
olderThan: "30d",
},
},
{
id: "keep-tagged-release",
action: "KEEP",
condition: {
tagState: "TAGGED",
tagPrefixes: ["release"],
packageNamePrefixes: [
"webapp",
"mobile",
],
},
},
{
id: "keep-minimum-versions",
action: "KEEP",
mostRecentVersions: {
packageNamePrefixes: [
"webapp",
"mobile",
"sandbox",
],
keepCount: 5,
},
},
],
});
import pulumi
import pulumi_gcp as gcp
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="my-repository",
description="example docker repository with cleanup policies",
format="DOCKER",
cleanup_policy_dry_run=False,
cleanup_policies=[
{
"id": "delete-untagged",
"action": "DELETE",
"condition": {
"tag_state": "UNTAGGED",
},
},
{
"id": "keep-new-untagged",
"action": "KEEP",
"condition": {
"tag_state": "UNTAGGED",
"newer_than": "7d",
},
},
{
"id": "delete-prerelease",
"action": "DELETE",
"condition": {
"tag_state": "TAGGED",
"tag_prefixes": [
"alpha",
"v0",
],
"older_than": "30d",
},
},
{
"id": "keep-tagged-release",
"action": "KEEP",
"condition": {
"tag_state": "TAGGED",
"tag_prefixes": ["release"],
"package_name_prefixes": [
"webapp",
"mobile",
],
},
},
{
"id": "keep-minimum-versions",
"action": "KEEP",
"most_recent_versions": {
"package_name_prefixes": [
"webapp",
"mobile",
"sandbox",
],
"keep_count": 5,
},
},
])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("my-repository"),
Description: pulumi.String("example docker repository with cleanup policies"),
Format: pulumi.String("DOCKER"),
CleanupPolicyDryRun: pulumi.Bool(false),
CleanupPolicies: artifactregistry.RepositoryCleanupPolicyArray{
&artifactregistry.RepositoryCleanupPolicyArgs{
Id: pulumi.String("delete-untagged"),
Action: pulumi.String("DELETE"),
Condition: &artifactregistry.RepositoryCleanupPolicyConditionArgs{
TagState: pulumi.String("UNTAGGED"),
},
},
&artifactregistry.RepositoryCleanupPolicyArgs{
Id: pulumi.String("keep-new-untagged"),
Action: pulumi.String("KEEP"),
Condition: &artifactregistry.RepositoryCleanupPolicyConditionArgs{
TagState: pulumi.String("UNTAGGED"),
NewerThan: pulumi.String("7d"),
},
},
&artifactregistry.RepositoryCleanupPolicyArgs{
Id: pulumi.String("delete-prerelease"),
Action: pulumi.String("DELETE"),
Condition: &artifactregistry.RepositoryCleanupPolicyConditionArgs{
TagState: pulumi.String("TAGGED"),
TagPrefixes: pulumi.StringArray{
pulumi.String("alpha"),
pulumi.String("v0"),
},
OlderThan: pulumi.String("30d"),
},
},
&artifactregistry.RepositoryCleanupPolicyArgs{
Id: pulumi.String("keep-tagged-release"),
Action: pulumi.String("KEEP"),
Condition: &artifactregistry.RepositoryCleanupPolicyConditionArgs{
TagState: pulumi.String("TAGGED"),
TagPrefixes: pulumi.StringArray{
pulumi.String("release"),
},
PackageNamePrefixes: pulumi.StringArray{
pulumi.String("webapp"),
pulumi.String("mobile"),
},
},
},
&artifactregistry.RepositoryCleanupPolicyArgs{
Id: pulumi.String("keep-minimum-versions"),
Action: pulumi.String("KEEP"),
MostRecentVersions: &artifactregistry.RepositoryCleanupPolicyMostRecentVersionsArgs{
PackageNamePrefixes: pulumi.StringArray{
pulumi.String("webapp"),
pulumi.String("mobile"),
pulumi.String("sandbox"),
},
KeepCount: pulumi.Int(5),
},
},
},
})
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 my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "my-repository",
Description = "example docker repository with cleanup policies",
Format = "DOCKER",
CleanupPolicyDryRun = false,
CleanupPolicies = new[]
{
new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyArgs
{
Id = "delete-untagged",
Action = "DELETE",
Condition = new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyConditionArgs
{
TagState = "UNTAGGED",
},
},
new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyArgs
{
Id = "keep-new-untagged",
Action = "KEEP",
Condition = new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyConditionArgs
{
TagState = "UNTAGGED",
NewerThan = "7d",
},
},
new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyArgs
{
Id = "delete-prerelease",
Action = "DELETE",
Condition = new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyConditionArgs
{
TagState = "TAGGED",
TagPrefixes = new[]
{
"alpha",
"v0",
},
OlderThan = "30d",
},
},
new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyArgs
{
Id = "keep-tagged-release",
Action = "KEEP",
Condition = new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyConditionArgs
{
TagState = "TAGGED",
TagPrefixes = new[]
{
"release",
},
PackageNamePrefixes = new[]
{
"webapp",
"mobile",
},
},
},
new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyArgs
{
Id = "keep-minimum-versions",
Action = "KEEP",
MostRecentVersions = new Gcp.ArtifactRegistry.Inputs.RepositoryCleanupPolicyMostRecentVersionsArgs
{
PackageNamePrefixes = new[]
{
"webapp",
"mobile",
"sandbox",
},
KeepCount = 5,
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryCleanupPolicyArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryCleanupPolicyConditionArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryCleanupPolicyMostRecentVersionsArgs;
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 my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("my-repository")
.description("example docker repository with cleanup policies")
.format("DOCKER")
.cleanupPolicyDryRun(false)
.cleanupPolicies(
RepositoryCleanupPolicyArgs.builder()
.id("delete-untagged")
.action("DELETE")
.condition(RepositoryCleanupPolicyConditionArgs.builder()
.tagState("UNTAGGED")
.build())
.build(),
RepositoryCleanupPolicyArgs.builder()
.id("keep-new-untagged")
.action("KEEP")
.condition(RepositoryCleanupPolicyConditionArgs.builder()
.tagState("UNTAGGED")
.newerThan("7d")
.build())
.build(),
RepositoryCleanupPolicyArgs.builder()
.id("delete-prerelease")
.action("DELETE")
.condition(RepositoryCleanupPolicyConditionArgs.builder()
.tagState("TAGGED")
.tagPrefixes(
"alpha",
"v0")
.olderThan("30d")
.build())
.build(),
RepositoryCleanupPolicyArgs.builder()
.id("keep-tagged-release")
.action("KEEP")
.condition(RepositoryCleanupPolicyConditionArgs.builder()
.tagState("TAGGED")
.tagPrefixes("release")
.packageNamePrefixes(
"webapp",
"mobile")
.build())
.build(),
RepositoryCleanupPolicyArgs.builder()
.id("keep-minimum-versions")
.action("KEEP")
.mostRecentVersions(RepositoryCleanupPolicyMostRecentVersionsArgs.builder()
.packageNamePrefixes(
"webapp",
"mobile",
"sandbox")
.keepCount(5)
.build())
.build())
.build());
}
}
resources:
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: my-repository
description: example docker repository with cleanup policies
format: DOCKER
cleanupPolicyDryRun: false
cleanupPolicies:
- id: delete-untagged
action: DELETE
condition:
tagState: UNTAGGED
- id: keep-new-untagged
action: KEEP
condition:
tagState: UNTAGGED
newerThan: 7d
- id: delete-prerelease
action: DELETE
condition:
tagState: TAGGED
tagPrefixes:
- alpha
- v0
olderThan: 30d
- id: keep-tagged-release
action: KEEP
condition:
tagState: TAGGED
tagPrefixes:
- release
packageNamePrefixes:
- webapp
- mobile
- id: keep-minimum-versions
action: KEEP
mostRecentVersions:
packageNamePrefixes:
- webapp
- mobile
- sandbox
keepCount: 5
The cleanupPolicies array defines deletion rules. Each policy has an action (DELETE or KEEP) and a condition (tagState, age, tag prefixes, or version count). Policies are evaluated in order; KEEP policies override DELETE policies. Setting cleanupPolicyDryRun to false enables actual deletion; true only logs what would be deleted.
Authenticate to Docker Hub with stored credentials
Private Docker Hub repositories or rate-limited public access require authentication stored in Secret Manager.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = gcp.organizations.getProject({});
const example_remote_secret = new gcp.secretmanager.Secret("example-remote-secret", {
secretId: "example-secret",
replication: {
auto: {},
},
});
const example_remote_secretVersion = new gcp.secretmanager.SecretVersion("example-remote-secret_version", {
secret: example_remote_secret.id,
secretData: "remote-password",
});
const secret_access = new gcp.secretmanager.SecretIamMember("secret-access", {
secretId: example_remote_secret.id,
role: "roles/secretmanager.secretAccessor",
member: project.then(project => `serviceAccount:service-${project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com`),
});
const my_repo = new gcp.artifactregistry.Repository("my-repo", {
location: "us-central1",
repositoryId: "example-dockerhub-remote",
description: "example remote dockerhub repository with credentials",
format: "DOCKER",
mode: "REMOTE_REPOSITORY",
remoteRepositoryConfig: {
description: "docker hub with custom credentials",
disableUpstreamValidation: true,
dockerRepository: {
publicRepository: "DOCKER_HUB",
},
upstreamCredentials: {
usernamePasswordCredentials: {
username: "remote-username",
passwordSecretVersion: example_remote_secretVersion.name,
},
},
},
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.get_project()
example_remote_secret = gcp.secretmanager.Secret("example-remote-secret",
secret_id="example-secret",
replication={
"auto": {},
})
example_remote_secret_version = gcp.secretmanager.SecretVersion("example-remote-secret_version",
secret=example_remote_secret.id,
secret_data="remote-password")
secret_access = gcp.secretmanager.SecretIamMember("secret-access",
secret_id=example_remote_secret.id,
role="roles/secretmanager.secretAccessor",
member=f"serviceAccount:service-{project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com")
my_repo = gcp.artifactregistry.Repository("my-repo",
location="us-central1",
repository_id="example-dockerhub-remote",
description="example remote dockerhub repository with credentials",
format="DOCKER",
mode="REMOTE_REPOSITORY",
remote_repository_config={
"description": "docker hub with custom credentials",
"disable_upstream_validation": True,
"docker_repository": {
"public_repository": "DOCKER_HUB",
},
"upstream_credentials": {
"username_password_credentials": {
"username": "remote-username",
"password_secret_version": example_remote_secret_version.name,
},
},
})
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/artifactregistry"
"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 {
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
example_remote_secret, err := secretmanager.NewSecret(ctx, "example-remote-secret", &secretmanager.SecretArgs{
SecretId: pulumi.String("example-secret"),
Replication: &secretmanager.SecretReplicationArgs{
Auto: &secretmanager.SecretReplicationAutoArgs{},
},
})
if err != nil {
return err
}
example_remote_secretVersion, err := secretmanager.NewSecretVersion(ctx, "example-remote-secret_version", &secretmanager.SecretVersionArgs{
Secret: example_remote_secret.ID(),
SecretData: pulumi.String("remote-password"),
})
if err != nil {
return err
}
_, err = secretmanager.NewSecretIamMember(ctx, "secret-access", &secretmanager.SecretIamMemberArgs{
SecretId: example_remote_secret.ID(),
Role: pulumi.String("roles/secretmanager.secretAccessor"),
Member: pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-artifactregistry.iam.gserviceaccount.com", project.Number),
})
if err != nil {
return err
}
_, err = artifactregistry.NewRepository(ctx, "my-repo", &artifactregistry.RepositoryArgs{
Location: pulumi.String("us-central1"),
RepositoryId: pulumi.String("example-dockerhub-remote"),
Description: pulumi.String("example remote dockerhub repository with credentials"),
Format: pulumi.String("DOCKER"),
Mode: pulumi.String("REMOTE_REPOSITORY"),
RemoteRepositoryConfig: &artifactregistry.RepositoryRemoteRepositoryConfigArgs{
Description: pulumi.String("docker hub with custom credentials"),
DisableUpstreamValidation: pulumi.Bool(true),
DockerRepository: &artifactregistry.RepositoryRemoteRepositoryConfigDockerRepositoryArgs{
PublicRepository: pulumi.String("DOCKER_HUB"),
},
UpstreamCredentials: &artifactregistry.RepositoryRemoteRepositoryConfigUpstreamCredentialsArgs{
UsernamePasswordCredentials: &artifactregistry.RepositoryRemoteRepositoryConfigUpstreamCredentialsUsernamePasswordCredentialsArgs{
Username: pulumi.String("remote-username"),
PasswordSecretVersion: example_remote_secretVersion.Name,
},
},
},
})
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 project = Gcp.Organizations.GetProject.Invoke();
var example_remote_secret = new Gcp.SecretManager.Secret("example-remote-secret", new()
{
SecretId = "example-secret",
Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
{
Auto = null,
},
});
var example_remote_secretVersion = new Gcp.SecretManager.SecretVersion("example-remote-secret_version", new()
{
Secret = example_remote_secret.Id,
SecretData = "remote-password",
});
var secret_access = new Gcp.SecretManager.SecretIamMember("secret-access", new()
{
SecretId = example_remote_secret.Id,
Role = "roles/secretmanager.secretAccessor",
Member = $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-artifactregistry.iam.gserviceaccount.com",
});
var my_repo = new Gcp.ArtifactRegistry.Repository("my-repo", new()
{
Location = "us-central1",
RepositoryId = "example-dockerhub-remote",
Description = "example remote dockerhub repository with credentials",
Format = "DOCKER",
Mode = "REMOTE_REPOSITORY",
RemoteRepositoryConfig = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigArgs
{
Description = "docker hub with custom credentials",
DisableUpstreamValidation = true,
DockerRepository = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigDockerRepositoryArgs
{
PublicRepository = "DOCKER_HUB",
},
UpstreamCredentials = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigUpstreamCredentialsArgs
{
UsernamePasswordCredentials = new Gcp.ArtifactRegistry.Inputs.RepositoryRemoteRepositoryConfigUpstreamCredentialsUsernamePasswordCredentialsArgs
{
Username = "remote-username",
PasswordSecretVersion = example_remote_secretVersion.Name,
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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.secretmanager.SecretIamMember;
import com.pulumi.gcp.secretmanager.SecretIamMemberArgs;
import com.pulumi.gcp.artifactregistry.Repository;
import com.pulumi.gcp.artifactregistry.RepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigDockerRepositoryArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigUpstreamCredentialsArgs;
import com.pulumi.gcp.artifactregistry.inputs.RepositoryRemoteRepositoryConfigUpstreamCredentialsUsernamePasswordCredentialsArgs;
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) {
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var example_remote_secret = new Secret("example-remote-secret", SecretArgs.builder()
.secretId("example-secret")
.replication(SecretReplicationArgs.builder()
.auto(SecretReplicationAutoArgs.builder()
.build())
.build())
.build());
var example_remote_secretVersion = new SecretVersion("example-remote-secretVersion", SecretVersionArgs.builder()
.secret(example_remote_secret.id())
.secretData("remote-password")
.build());
var secret_access = new SecretIamMember("secret-access", SecretIamMemberArgs.builder()
.secretId(example_remote_secret.id())
.role("roles/secretmanager.secretAccessor")
.member(String.format("serviceAccount:service-%s@gcp-sa-artifactregistry.iam.gserviceaccount.com", project.number()))
.build());
var my_repo = new Repository("my-repo", RepositoryArgs.builder()
.location("us-central1")
.repositoryId("example-dockerhub-remote")
.description("example remote dockerhub repository with credentials")
.format("DOCKER")
.mode("REMOTE_REPOSITORY")
.remoteRepositoryConfig(RepositoryRemoteRepositoryConfigArgs.builder()
.description("docker hub with custom credentials")
.disableUpstreamValidation(true)
.dockerRepository(RepositoryRemoteRepositoryConfigDockerRepositoryArgs.builder()
.publicRepository("DOCKER_HUB")
.build())
.upstreamCredentials(RepositoryRemoteRepositoryConfigUpstreamCredentialsArgs.builder()
.usernamePasswordCredentials(RepositoryRemoteRepositoryConfigUpstreamCredentialsUsernamePasswordCredentialsArgs.builder()
.username("remote-username")
.passwordSecretVersion(example_remote_secretVersion.name())
.build())
.build())
.build())
.build());
}
}
resources:
example-remote-secret:
type: gcp:secretmanager:Secret
properties:
secretId: example-secret
replication:
auto: {}
example-remote-secretVersion:
type: gcp:secretmanager:SecretVersion
name: example-remote-secret_version
properties:
secret: ${["example-remote-secret"].id}
secretData: remote-password
secret-access:
type: gcp:secretmanager:SecretIamMember
properties:
secretId: ${["example-remote-secret"].id}
role: roles/secretmanager.secretAccessor
member: serviceAccount:service-${project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com
my-repo:
type: gcp:artifactregistry:Repository
properties:
location: us-central1
repositoryId: example-dockerhub-remote
description: example remote dockerhub repository with credentials
format: DOCKER
mode: REMOTE_REPOSITORY
remoteRepositoryConfig:
description: docker hub with custom credentials
disableUpstreamValidation: true
dockerRepository:
publicRepository: DOCKER_HUB
upstreamCredentials:
usernamePasswordCredentials:
username: remote-username
passwordSecretVersion: ${["example-remote-secretVersion"].name}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The upstreamCredentials block references a Secret Manager secret containing the password. The usernamePasswordCredentials specify the username and passwordSecretVersion. The SecretIamMember grants the Artifact Registry service account permission to read the secret. Setting disableUpstreamValidation to true skips connectivity checks during repository creation.
Beyond these examples
These snippets focus on specific repository-level features: regional and multi-region deployment, virtual and remote repository modes, cleanup policies and encryption, and authentication for external registries. They’re intentionally minimal rather than full artifact management solutions.
The examples may reference pre-existing infrastructure such as KMS keys for customer-managed encryption and upstream repositories for virtual repository routing. They focus on configuring the repository rather than provisioning everything around it.
To keep things focused, common repository patterns are omitted, including:
- Format-specific configurations (Maven, NPM, Python, APT, YUM)
- Vulnerability scanning configuration
- Custom remote repository URIs for non-Docker formats
- Common repository mode for Artifact Registry pull-through caching
These omissions are intentional: the goal is to illustrate how each repository feature is wired, not provide drop-in artifact management modules. See the Artifact Registry Repository resource reference for all available configuration options.
Let's create GCP Artifact Registry Repositories
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Repository Configuration & Immutability
format, location, project, repositoryId, kmsKeyName, mode, and remoteRepositoryConfig.location to asia, europe, or us instead of a specific region for multi-region repositories.Repository Modes & Types
STANDARD_REPOSITORY (default, stores your artifacts), VIRTUAL_REPOSITORY (aggregates multiple upstream repositories), and REMOTE_REPOSITORY (caches artifacts from external sources like Docker Hub).mode to VIRTUAL_REPOSITORY and configure virtualRepositoryConfig.upstreamPolicies with repository references and priority values. Lower priority numbers are checked first.DOCKER_HUB, DEBIAN, ROCKY) or custom repositories by specifying a URI. For another Artifact Registry repository, use commonRepository.uri with the repository ID or full URL.Authentication & Security
remoteRepositoryConfig.upstreamCredentials.usernamePasswordCredentials with a username and passwordSecretVersion pointing to a Secret Manager secret. Grant the Artifact Registry service account (service-PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com) the roles/secretmanager.secretAccessor role.kmsKeyName to your Cloud KMS key resource name. You must grant the Artifact Registry service account (service-PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com) the roles/cloudkms.cryptoKeyEncrypterDecrypter role before creating the repository. Use dependsOn to ensure the IAM binding is created first.Cleanup Policies & Maintenance
cleanupPolicies with conditions like tagState (TAGGED/UNTAGGED), newerThan/olderThan (duration), tagPrefixes, and packageNamePrefixes. Each policy has an action (DELETE or KEEP) and a unique ID. Use mostRecentVersions.keepCount to retain a minimum number of versions.cleanupPolicyDryRun to true to prevent the cleanup pipeline from actually deleting versions while you test your policies.Labels & Metadata
labels field is non-authoritative and only manages labels present in your configuration. Labels set outside Pulumi won’t be removed. Use the effectiveLabels output property to see all labels on the resource.Docker-Specific Configuration
dockerConfig.immutableTags to true to prevent tag mutation in Docker repositories.Using a different cloud?
Explore containers guides for other cloud providers: