How to Copy a Custom VM Image Between Google Cloud Projects Programmatically


2 views

When working with multiple Google Cloud Platform projects, you might create a valuable custom VM image in one project (let's call it project-1) that needs to be available in another project (project-2). This scenario is common when:

  • Sharing development environments across teams
  • Promoting images from staging to production
  • Maintaining standardized base images across projects

Before proceeding, ensure you have:

  • Owner or Compute Engine Admin role in both projects
  • Google Cloud SDK installed (gcloud command-line tool)
  • Enabled Compute Engine API in both projects

The most straightforward approach is using the gcloud command-line tool:

# Export the image from project-1 to Cloud Storage
gcloud compute images export \
    --destination-uri gs://your-bucket-name/image-name.tar.gz \
    --image image-name \
    --project project-1

# Import the image to project-2
gcloud compute images import image-name \
    --source-file gs://your-bucket-name/image-name.tar.gz \
    --project project-2

An alternative approach is to share the image directly between projects without exporting/importing:

# Add IAM policy binding to allow project-2 to use the image
gcloud projects add-iam-policy-binding project-1 \
    --member="serviceAccount:service-project-number@compute-system.iam.gserviceaccount.com" \
    --role="roles/compute.imageUser"

Replace service-project-number with project-2's numeric ID (found in Project Settings).

For infrastructure-as-code approach, here's a Terraform example:

resource "google_compute_image" "project2_image" {
  name         = "copied-image"
  source_image = "projects/project-1/global/images/source-image-name"
  project      = "project-2"
}

If you encounter permission issues, verify:

  • Proper IAM roles are assigned in both projects
  • The Compute Engine service account has necessary permissions
  • Storage buckets (if used) have correct access controls

For large images, consider these optimizations:

  • Use regional storage buckets closer to your instances
  • Compress images before transfer (though GCP handles this automatically)
  • Schedule image transfers during low-usage periods

For frequent image sharing, create a Cloud Function triggered by new image creation:

def copy_image(data, context):
    from googleapiclient import discovery
    
    compute = discovery.build('compute', 'v1')
    
    source_project = data['attributes']['projectId']
    image_name = data['attributes']['resourceName'].split('/')[-1]
    
    image = compute.images().get(project=source_project, image=image_name).execute()
    
    # Create the same image in target project
    compute.images().insert(
        project='project-2',
        body=image
    ).execute()

Working with multiple Google Cloud projects often requires sharing resources between them. A common scenario is when you've created a perfectly configured custom VM image in Project A (let's say prod-project-123) that needs to be available in Project B (dev-project-456). Here's how to accomplish this efficiently.

Before proceeding, ensure you have:

  • Owner or Compute Image User roles in both projects
  • gcloud CLI installed and authenticated
  • Image name and project details handy

First, identify your source image in Project A:

gcloud compute images list --project=prod-project-123

Then create a copy in Project B:

gcloud compute images create new-image-name \
    --project=dev-project-456 \
    --source-image=projects/prod-project-123/global/images/source-image-name

For better management, consider using image families:

gcloud compute images create new-image-name \
    --project=dev-project-456 \
    --family=my-app-base \
    --source-image=projects/prod-project-123/global/images/source-image-name

For infrastructure-as-code users, here's the Terraform equivalent:

resource "google_compute_image" "imported" {
  project = "dev-project-456"
  name    = "imported-image"
  family  = "my-app-base"
  source_image = "projects/prod-project-123/global/images/source-image-name"
}

After copying, verify the image exists in the target project:

gcloud compute images describe imported-image \
    --project=dev-project-456

Now you can create instances using this image:

gcloud compute instances create new-vm \
    --project=dev-project-456 \
    --image=imported-image \
    --image-project=dev-project-456

If you encounter permission issues, ensure the service account has:

  • roles/compute.imageUser on the source image
  • roles/compute.admin in the target project

Grant permissions with:

gcloud projects add-iam-policy-binding prod-project-123 \
    --member='serviceAccount:dev-project-456@cloudservices.gserviceaccount.com' \
    --role='roles/compute.imageUser'