Create custom images

Linux

You can create custom images from source disks, images, snapshots, or imagesstored in Cloud Storage and use these images to create virtual machine (VM)instances. Custom images are ideal for situations where you have created andmodified a persistent boot disk or specific image to a certain state and need tosave that state for creating VMs.

Alternatively, you can use thevirtual disk importtool to import boot disk imagesto Compute Engine from your existing systems and add them to your customimages list.

Note: If you want to create incremental backups of your persistent disk data,usesnapshots instead.

Before you begin

Create a custom image

This section describes how to create a custom image on a Linux VM. Forinformation about creating a Windows image, seeCreating a Windowsimage.

Select an image storage location

When creating a custom image, you can specify the image'sCloud Storage location, excluding dual-regionlocations. By specifying the image storage location, you can meet yourregulatory and compliance requirements for data locality as well as your highavailability needs by providing redundancy across regions. To create, modify,and delete images stored in Cloud Storage, you must haveroles/compute.storageAdmin.

The storage location feature is optional. If you don't select a location,Compute Engine stores your image in the multi-region closest to theimage source. For example, when you create an image from a source disk that islocated inus-central1 and if you don't specify a location for the customimage, then Compute Engine stores the image in theus multi-region.

If the image is not available in a region where you are creating aVM, Compute Engine caches the image in that region the first time youcreate a VM.

To see the location where an image is stored, use theimages describecommand fromgcloud compute:

gcloud compute images describeIMAGE_NAME \    --project=PROJECT_ID

Replace the following:

  • IMAGE_NAME: the name of your image.

  • PROJECT_ID: the project ID to which the image belongs.

All of your existing images prior to this feature launch remain where they are,the only change is that you can view the image location of all your images. Ifyou have an existing image you want to move, you must recreate it in the newlocation.

Prepare your VM for an image

You can create an image from a disk even while it is attached to a runningVM. However, your image is more reliable if you put the VMin a state that is easier for the image to capture. This section describes howto prepare your boot disk for the image.

Minimize writing data to the persistent disk

Use one of the following processes to reduce the disk writes:

  • Stop the VMso that it can shut down and stop writing any data to the persistent disk.

  • If you can't stop your VM before you create the image, minimize theamount of writes to the disk and sync your file system. To minimizewriting to your persistent disk, follow these steps:

    1. Pause apps or operating system processes that write data tothat persistent disk.
    2. Run an app flush to disk if necessary. For example, MySQL has aFLUSH statement. Other apps might have similar processes.
    3. Stop your apps from writing to your persistent disk.
    4. Runsudo sync.

Disable the auto-delete option for the disk

By default, the auto-delete option is enabled on the boot disks. Before creatingan image from a disk, disable auto-delete to prevent the disk from beingautomatically deleted when you delete the VM.

To disable auto-delete for the disk, use one of the following methods:

Console

  1. In the Google Cloud console, go to theVM instances page.

    Go to the VM instances page

  2. Click the name of the VM that you're using as the source for creatingan image.

    TheVM instance details page displays.

  3. ClickEdit.

  4. In theBoot disk section, for theDeletion rule, check thattheKeep disk option is selected.

  5. ClickSave.

gcloud

In the Google Cloud CLI, use thegcloud compute instances set-disk-auto-delete commandto disable the auto-delete option for the disk.

gcloud compute instances set-disk-auto-deleteVM_NAME \    --no-auto-delete \    --disk=SOURCE_DISK

Replace the following:

  • VM_NAME: the name of your VM instance.
  • SOURCE_DISK: the name of the disk from which you want to create the image.

Go

Go

Before trying this sample, follow theGo setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineGo API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb")// setDiskAutodelete sets the autodelete flag of a disk to given value.funcsetDiskAutoDelete(wio.Writer,projectID,zone,instanceName,diskNamestring,autoDeletebool,)error{// projectID := "your_project_id"// zone := "us-west3-b"// instanceName := "your_instance_name"// diskName := "your_disk_name"// autoDelete := truectx:=context.Background()instancesClient,err:=compute.NewInstancesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewInstancesRESTClient: %w",err)}deferinstancesClient.Close()getInstanceReq:=&computepb.GetInstanceRequest{Project:projectID,Zone:zone,Instance:instanceName,}instance,err:=instancesClient.Get(ctx,getInstanceReq)iferr!=nil{returnfmt.Errorf("unable to get instance: %w",err)}diskExists:=falsefor_,disk:=rangeinstance.GetDisks(){ifdisk.GetDeviceName()==diskName{diskExists=truebreak}}if!diskExists{returnfmt.Errorf("instance %s doesn't have a disk named %s attached",instanceName,diskName,)}req:=&computepb.SetDiskAutoDeleteInstanceRequest{Project:projectID,Zone:zone,Instance:instanceName,DeviceName:diskName,AutoDelete:autoDelete,}op,err:=instancesClient.SetDiskAutoDelete(ctx,req)iferr!=nil{returnfmt.Errorf("unable to set disk autodelete field: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"disk autoDelete field updated.\n")returnnil}

Java

Java

Before trying this sample, follow theJava setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineJava API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

importcom.google.cloud.compute.v1.Instance;importcom.google.cloud.compute.v1.InstancesClient;importcom.google.cloud.compute.v1.Operation;importcom.google.cloud.compute.v1.SetDiskAutoDeleteInstanceRequest;importjava.io.IOException;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassSetDiskAutodelete{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// Project ID or project number of the Cloud project you want to use.StringprojectId="YOUR_PROJECT_ID";// The zone of the disk that you want to modify.Stringzone="europe-central2-b";// Name of the instance the disk is attached to.StringinstanceName="YOUR_INSTANCE_NAME";// The name of the disk for which you want to modify the autodelete flag.StringdiskName="YOUR_DISK_NAME";// The new value of the autodelete flag.booleanautoDelete=true;setDiskAutodelete(projectId,zone,instanceName,diskName,autoDelete);}// Sets the autodelete flag of a disk to given value.publicstaticvoidsetDiskAutodelete(StringprojectId,Stringzone,StringinstanceName,StringdiskName,booleanautoDelete)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests. After completing all of your requests, call// the `instancesClient.close()` method on the client to safely// clean up any remaining background resources.try(InstancesClientinstancesClient=InstancesClient.create()){// Retrieve the instance given by the instanceName.Instanceinstance=instancesClient.get(projectId,zone,instanceName);// Check if the instance contains a disk that matches the given diskName.booleandiskNameMatch=instance.getDisksList().stream().anyMatch(disk->disk.getDeviceName().equals(diskName));if(!diskNameMatch){thrownewError(String.format("Instance %s doesn't have a disk named %s attached",instanceName,diskName));}// Create the request object.SetDiskAutoDeleteInstanceRequestrequest=SetDiskAutoDeleteInstanceRequest.newBuilder().setProject(projectId).setZone(zone).setInstance(instanceName).setDeviceName(diskName)// Update the autodelete property..setAutoDelete(autoDelete).build();// Wait for the update instance operation to complete.Operationresponse=instancesClient.setDiskAutoDeleteAsync(request).get(3,TimeUnit.MINUTES);if(response.hasError()){System.out.println("Failed to update Disk autodelete field!"+response);return;}System.out.println("Disk autodelete field updated. Operation Status: "+response.getStatus());}}}

Node.js

Node.js

Before trying this sample, follow theNode.js setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineNode.js API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

/** * TODO(developer): Uncomment and replace these variables before running the sample. */// const projectId = 'YOUR_PROJECT_ID';// const zone = 'europe-central2-b';// const instanceName = 'YOUR_INSTANCE_NAME';// const diskName = 'YOUR_DISK_NAME';// const autoDelete = true;constcompute=require('@google-cloud/compute');asyncfunctionsetDiskAutodelete(){constinstancesClient=newcompute.InstancesClient();const[instance]=awaitinstancesClient.get({project:projectId,zone,instance:instanceName,});if(!instance.disks.some(disk=>disk.deviceName===diskName)){thrownewError(`Instance${instanceName} doesn't have a disk named${diskName} attached.`);}const[response]=awaitinstancesClient.setDiskAutoDelete({project:projectId,zone,instance:instanceName,deviceName:diskName,autoDelete,});letoperation=response.latestResponse;constoperationsClient=newcompute.ZoneOperationsClient();// Wait for the update instance operation to complete.while(operation.status!=='DONE'){[operation]=awaitoperationsClient.wait({operation:operation.name,project:projectId,zone:operation.zone.split('/').pop(),});}console.log('Disk autoDelete field updated.');}setDiskAutodelete();

Python

Python

Before trying this sample, follow thePython setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EnginePython API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

from__future__importannotationsimportsysfromtypingimportAnyfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_for_extended_operation(operation:ExtendedOperation,verbose_name:str="operation",timeout:int=300)->Any:"""    Waits for the extended (long-running) operation to complete.    If the operation is successful, it will return its result.    If the operation ends with an error, an exception will be raised.    If there were any warnings during the execution of the operation    they will be printed to sys.stderr.    Args:        operation: a long-running operation you want to wait on.        verbose_name: (optional) a more verbose name of the operation,            used only during error and warning reporting.        timeout: how long (in seconds) to wait for operation to finish.            If None, wait indefinitely.    Returns:        Whatever the operation.result() returns.    Raises:        This method will raise the exception received from `operation.exception()`        or RuntimeError if there is no exception set, but there is an `error_code`        set for the `operation`.        In case of an operation taking longer than `timeout` seconds to complete,        a `concurrent.futures.TimeoutError` will be raised.    """result=operation.result(timeout=timeout)ifoperation.error_code:print(f"Error during{verbose_name}: [Code:{operation.error_code}]:{operation.error_message}",file=sys.stderr,flush=True,)print(f"Operation ID:{operation.name}",file=sys.stderr,flush=True)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultdefset_disk_autodelete(project_id:str,zone:str,instance_name:str,disk_name:str,autodelete:bool)->None:"""    Set the autodelete flag of a disk to given value.    Args:        project_id: project ID or project number of the Cloud project you want to use.        zone: name of the zone in which is the disk you want to modify.        instance_name: name of the instance the disk is attached to.        disk_name: the name of the disk which flag you want to modify.        autodelete: the new value of the autodelete flag.    """instance_client=compute_v1.InstancesClient()instance=instance_client.get(project=project_id,zone=zone,instance=instance_name)fordiskininstance.disks:ifdisk.device_name==disk_name:breakelse:raiseRuntimeError(f"Instance{instance_name} doesn't have a disk named{disk_name} attached.")disk.auto_delete=autodeleteoperation=instance_client.update(project=project_id,zone=zone,instance=instance_name,instance_resource=instance,)wait_for_extended_operation(operation,"disk update")

REST

To set the auto-delete option of a disk, make aPOST request to theinstances.setDiskAutoDelete method.

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/setDiskAutoDelete?autoDelete=false&deviceName=SOURCE_DISK

Replace the following:

  • PROJECT_ID: the project ID to which the source VM belongs.
  • ZONE: the zone where the source VM is located.
  • VM_NAME: the name of the source VM.
  • SOURCE_DISK: the device name of the disk from whichyou want to create the image.

After you prepare the VM,create the image.

Create the image

You can create disk images from the following sources:

  • A persistent disk, even while that disk is attached to a VM
  • A snapshot of a persistent disk
  • Another image in your project
  • An image that is shared from another project
  • Acompressed RAW imagein Cloud Storage

You can create a disk image once every 10 minutes. If you want to issuea burst of requests to create a disk image, you can issue at most 6 requestsin 60 minutes. For more information, seeSnapshot frequency limits.

Console

  1. In the Google Cloud console, go to theCreate an image page.

    Go to Create an image

  2. Specify theName of your image.

  3. Specify theSource from which you want to create an image. Thiscan be a persistent disk, a snapshot, another image, or a disk.raw filein Cloud Storage.

  4. If you are creating an image from a disk attached to a running VM,checkKeep instance running to confirm that you want to create theimage while the VM is running. You canprepare your VMbefore creating the image.

  5. In theBased on source disk location (default) drop-down list,specify the location to store the image. For example, specifyus tostore the image in theus multi-region, orus-central1 to store it intheus-central1 region. If you don't make a selection,Compute Engine stores the image in the multi-region closest toyour image's source location.

  6. Optional: specify the properties for your image.

    • Family: theimage familythis new image belongs to.
    • Description: a description for your custom image.
    • Label: alabel to grouptogether resources.
  7. Specify the encryption key. You can choose between a Google-owned and Google-managed encryption key,aCloud Key Management Service (Cloud KMS) key or acustomer-supplied encryption (CSEK)key. If no encryption key is specified, images are encryptedusing a Google-owned and Google-managed encryption key.

  8. ClickCreate to create the image.

gcloud

In the Google Cloud CLI, use thegcloud compute images create commandto create a custom image.

Create an image from a source disk:

The--force flag is an optional flag that lets you create theimage from a running instance. By default, you cannot create images from runninginstances. Specify this flag only if you are sure that you want to createthe image while the instance is running.

gcloud compute images createIMAGE_NAME \    --source-disk=SOURCE_DISK \    --source-disk-zone=ZONE \    [--family=IMAGE_FAMILY] \    [--storage-location=LOCATION] \    [--force]

Replace the following:

  • IMAGE_NAME: a name for the new image
  • SOURCE_DISK: the disk from which you want to create the image
  • ZONE: the zone where the disk is located
  • IMAGE_FAMILY: Optional: a flag that specifies whichimage family this image belongs to
  • LOCATION: Optional: a flag that lets you designate the region or multi-region where your image is stored. For example, specifyus to store the image in theus multi-region, orus-central1 to store it in theus-central1 region. If you don't make a selection, Compute Engine stores the image in the multi-region closest to your image's source location.

Create an image from a source image:

gcloud compute images createIMAGE_NAME \  --source-image=SOURCE_IMAGE \  [--source-image-project=IMAGE_PROJECT] \  [--family=IMAGE_FAMILY] \  [--storage-location=LOCATION]

Replace the following:

  • IMAGE_NAME: a name for the new image.
  • SOURCE_IMAGE: the image from which you want tocreate the new image.
  • IMAGE_PROJECT: Optional: the project the sourceimage is located in. Use this parameter if you want to copy an image fromanother project.
  • IMAGE_FAMILY: Optional: theimage family this new imagebelongs to.
  • LOCATION: Optional: lets you designate the regionor multi-region where your image is stored. For example, specifyus tostore the image in theus multi-region, orus-central1 to store it intheus-central1 region. If you don't make a selection,Compute Engine stores the image in the multi-region closest toyour image's source location.

Create an image from a snapshot:

gcloud compute images createIMAGE_NAME \    --source-snapshot=SOURCE_SNAPSHOT \    [--storage-location=LOCATION]

Replace the following:

  • IMAGE_NAME: a name for the new image
  • SOURCE_SNAPSHOT: the snapshot from which you want to create the image
  • LOCATION: Optional: a flag that lets you designate the region or multi-region where your image is stored. For example, specifyus to store the image in theus multi-region, orus-central1 to store it in theus-central1 region. If you don't make a selection, Compute Engine stores the image in the multi-region closest to your image's source location.

View an image location:

Use thegcloud compute images describe commandto view an image location.

gcloud compute images describeIMAGE_NAME

ReplaceIMAGE_NAME with the name of your image thatyou want to review.

Go

Go

Before trying this sample, follow theGo setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineGo API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb")// Creates a disk image from an existing diskfunccreateImageFromDisk(wio.Writer,projectID,zone,sourceDiskName,imageNamestring,storageLocations[]string,forceCreatebool,)error{// projectID := "your_project_id"// zone := "us-central1-a"// sourceDiskName := "your_disk_name"// imageName := "my_image"// // If storageLocations empty, automatically selects the closest one to the source// storageLocations = []string{}// // If forceCreate is set to `true`, proceeds even if the disk is attached to// // a running instance. This may compromise integrity of the image!// forceCreate = falsectx:=context.Background()disksClient,err:=compute.NewDisksRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewDisksRESTClient: %w",err)}deferdisksClient.Close()imagesClient,err:=compute.NewImagesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewImagesRESTClient: %w",err)}deferimagesClient.Close()// Get the source disksource_req:=&computepb.GetDiskRequest{Disk:sourceDiskName,Project:projectID,Zone:zone,}disk,err:=disksClient.Get(ctx,source_req)iferr!=nil{returnfmt.Errorf("unable to get source disk: %w",err)}// Create the imagereq:=computepb.InsertImageRequest{ForceCreate:&forceCreate,ImageResource:&computepb.Image{Name:&imageName,SourceDisk:disk.SelfLink,StorageLocations:storageLocations,},Project:projectID,}op,err:=imagesClient.Insert(ctx,&req)iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Disk image %s created\n",imageName)returnnil}

Java

Java

Before trying this sample, follow theJava setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineJava API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

importcom.google.cloud.compute.v1.Disk;importcom.google.cloud.compute.v1.DisksClient;importcom.google.cloud.compute.v1.Image;importcom.google.cloud.compute.v1.ImagesClient;importcom.google.cloud.compute.v1.InsertImageRequest;importcom.google.cloud.compute.v1.Instance;importcom.google.cloud.compute.v1.InstancesClient;importcom.google.cloud.compute.v1.Operation;importjava.io.IOException;importjava.util.Arrays;importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreateImage{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// Project ID or project number of the Cloud project you use.Stringproject="your-project-id";// Zone of the disk you copy from.Stringzone="europe-central2-b";// Name of the source disk you copy from.StringsourceDiskName="source-disk-name";// Name of the image you want to create.StringimageName="your-image-name";// Storage location for the image. If the value is undefined,// function will store the image in the multi-region closest to your image's source location.StringstorageLocation="eu";// Create the image even if the source disk is attached to a running instance.booleanforceCreate=false;createImage(project,zone,sourceDiskName,imageName,storageLocation,forceCreate);}// Creates a new disk image from the specified source disk.publicstaticvoidcreateImage(Stringproject,Stringzone,StringsourceDiskName,StringimageName,StringstorageLocation,booleanforceCreate)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests. After completing all of your requests, call// the `client.close()` method on the client to safely// clean up any remaining background resources.try(ImagesClientimagesClient=ImagesClient.create();InstancesClientinstancesClient=InstancesClient.create();DisksClientdisksClient=DisksClient.create()){Diskdisk=disksClient.get(project,zone,sourceDiskName);// Getting instances where source disk is attached.for(StringfullInstanceName:disk.getUsersList()){Map<String,String>instanceInfo=parseInstanceName(fullInstanceName);Instanceinstance=instancesClient.get(instanceInfo.get("instanceProjectId"),instanceInfo.get("instanceZone"),instanceInfo.get("instanceName"));// Сheck whether the instances are stopped.if(!Arrays.asList("TERMINATED","STOPPED").contains(instance.getStatus())            &&!forceCreate){thrownewIllegalStateException(String.format("Instance %s should be stopped. For Windows instances please stop the instance "+"using GCESysprep command. For Linux instances just shut it down normally."+" You can suppress this error and create an image of the disk by setting "+"'forceCreate' parameter to true (not recommended). "+"More information here: "+"* https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api"+"* https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image",instanceInfo.get("instanceName")));}}if(forceCreate){System.out.println("Warning: forceCreate option compromise the integrity of your image. "+"Stop the instance before you create the image if possible.");}// Create Image.IImageimage=IImagenewBuilder().setName(imageName).setSourceDisk(String.format("/zones/%s/disks/%s",zone,sourceDiskName)).addStorageLocations(storageLocation.isEmpty()?"":storageLocation).build();IInsertImageRequestinsertImageRequest=IInsertImageRequestnewBuilder().setProject(project).ssetForceCreateforceCreate).setImageResource(image).build();OOperationresponse=imagesClient.insertAsync(insertImageRequest).get(5,TimeUnit.MINUTES);if(rresponse.hasError(){System.out.println("Image creation failed ! ! "+response);return;}System.out.println("Image created.");}}publicstaticMap<String,String>parseInstanceName(Stringname){String[]parsedName=name.split("/");intsplitLength=parsedName.length;if(splitLength <5){thrownewIllegalArgumentException("Provide correct instance name in the following format: "+"https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME");}returnnewHashMap<>(){{put("instanceName",parsedName[splitLength-1]);put("instanceZone",parsedName[splitLength-3]);put("instanceProjectId",parsedName[splitLength-5]);}};}}

Python

Python

Before trying this sample, follow thePython setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EnginePython API reference documentation.

To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.

from__future__importannotationsimportsysfromtypingimportAnyimportwarningsfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_for_extended_operation(operation:ExtendedOperation,verbose_name:str="operation",timeout:int=300)->Any:"""    Waits for the extended (long-running) operation to complete.    If the operation is successful, it will return its result.    If the operation ends with an error, an exception will be raised.    If there were any warnings during the execution of the operation    they will be printed to sys.stderr.    Args:        operation: a long-running operation you want to wait on.        verbose_name: (optional) a more verbose name of the operation,            used only during error and warning reporting.        timeout: how long (in seconds) to wait for operation to finish.            If None, wait indefinitely.    Returns:        Whatever the operation.result() returns.    Raises:        This method will raise the exception received from `operation.exception()`        or RuntimeError if there is no exception set, but there is an `error_code`        set for the `operation`.        In case of an operation taking longer than `timeout` seconds to complete,        a `concurrent.futures.TimeoutError` will be raised.    """result=operation.result(timeout=timeout)ifoperation.error_code:print(f"Error during{verbose_name}: [Code:{operation.error_code}]:{operation.error_message}",file=sys.stderr,flush=True,)print(f"Operation ID:{operation.name}",file=sys.stderr,flush=True)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultSTOPPED_MACHINE_STATUS=(compute_v1.Instance.Status.TERMINATED.name,compute_v1.Instance.Status.STOPPED.name,)defcreate_image_from_disk(project_id:str,zone:str,source_disk_name:str,image_name:str,storage_location:str|None=None,force_create:bool=False,)->compute_v1.Image:"""    Creates a new disk image.    Args:        project_id: project ID or project number of the Cloud project you use.        zone: zone of the disk you copy from.        source_disk_name: name of the source disk you copy from.        image_name: name of the image you want to create.        storage_location: storage location for the image. If the value is undefined,            function will store the image in the multi-region closest to your image's            source location.        force_create: create the image even if the source disk is attached to a            running instance.    Returns:        An Image object.    """image_client=compute_v1.ImagesClient()disk_client=compute_v1.DisksClient()instance_client=compute_v1.InstancesClient()# Get source diskdisk=disk_client.get(project=project_id,zone=zone,disk=source_disk_name)fordisk_userindisk.users:instance_name=disk_user.split("/")[-1]instance=instance_client.get(project=project_id,zone=zone,instance=instance_name)ifinstance.statusinSTOPPED_MACHINE_STATUS:continueifnotforce_create:raiseRuntimeError(f"Instance{disk_user} should be stopped. For Windows instances please "f"stop the instance using `GCESysprep` command. For Linux instances just "f"shut it down normally. You can supress this error and create an image of"f"the disk by setting `force_create` parameter to true (not recommended).\n"f"More information here:\n"f" * https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api\n"f" * https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image")else:warnings.warn(f"Warning: The `force_create` option may compromise the integrity of your image. "f"Stop the{disk_user} instance before you create the image if possible.")# Create imageimage=compute_v1.Image()image.source_disk=disk.self_linkimage.name=image_nameifstorage_location:image.storage_locations=[storage_location]operation=image_client.insert(project=project_id,image_resource=image)wait_for_extended_operation(operation,"image creation from disk")returnimage_client.get(project=project_id,image=image_name)

REST

Make aPOST request to theimages().insert method,a URL in the request body that points to the source object from whichyou want to create the image. Specify URLs to your resources using yourown project ID and resource names.

Create an image from a persistent disk:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images{  "name": "IMAGE_NAME",  "sourceDisk": "/zones/ZONE/disks/SOURCE_DISK",  ("storageLocations": "LOCATION",)  ("forceCreate": "TRUE")}

Replace the following:

  • PROJECT_ID: the project ID to which the image belongs.
  • IMAGE_NAME: a name for the new image that you wantto create.
  • ZONE: the zone where the source disk is located.
  • SOURCE_DISK: the disk from which you want to createthe image.
  • LOCATION: Optional: the storage location of yourimage. For example, specifyus to store the image in theusmulti-region, orus-central1 to store it in theus-central1 region.If you don't make a selection, Compute Engine stores theimage in the multi-region closest to your image's source location.

The optionalforceCreate parameter lets you create the image from arunning VM. SpecifyTRUE only if you are sure that you want tocreate the image from a running VM. TheforceCreate default settingisFALSE.

Create an image from another image:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images{  "name": "IMAGE_NAME",  "sourceImage": "/global/images/SOURCE_IMAGE",  ("storageLocations": "LOCATION")}

Replace the following:

  • PROJECT_ID: the project to which the imagebelongs.
  • IMAGE_NAME: a name for the new image that youwant to create.
  • SOURCE_IMAGE: the image from which you want tocreate the image.
  • LOCATION: Optional: the storage location of yourimage. For example, specifyus to store the image in theus multi-region, orus-central1 to store it in theus-central1region. If you don't make a selection, Compute Engine storesthe image in the multi-region closest to your image's source location.

Create an image from a snapshot:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images{  "name": "IMAGE_NAME",  "sourceSnapshot": "(/SOURCE_PROJECT_ID)/global/snapshots/SOURCE_SNAPSHOT",  ("storageLocations": "LOCATION")}

Replace the following:

  • PROJECT_ID: the project to which the image belongs.
  • IMAGE_NAME: a name for the new image that you wantto create.
  • SOURCE_PROJECT_ID: Optional: the project thesnapshot is located in. You must have permission to access the snapshotresource in that project.
  • SOURCE_SNAPSHOT: the snapshot from which you wantto create the image.
  • LOCATION: Optional: the storage location of yourimage. For example, specifyus to store the image in theusmulti-region, orus-central1 to store it in theus-central1 region.If you don't make a selection, Compute Engine stores theimage in the multi-region closest to your image's source location.

For more information about adding images, see theimages reference.

Share the image

After creating a custom image, you canshare it acrossprojects. If you allow users from another project to use your customimages, then they canaccess these images by specifying the imageproject intheir request.

Enable guest operating system features

Use guest operating system (OS) features to configure the following networking,security, storage, and OS options on custom images. Custom imageswith these configured features are used as boot disks.

gcloud

Use thegcloud compute imagescreate command with the--guest-os-features flag to create a new custom image from an existingcustom image.

gcloud compute images createIMAGE_NAME \    --source-image=SOURCE_IMAGE \    [--source-image-project=IMAGE_PROJECT] \    --guest-os-features="FEATURES,..." \    [--storage-location=LOCATION]

Replace the following:

  • IMAGE_NAME: the name for the new image
  • SOURCE_IMAGE: an image to base the new image on
  • IMAGE_PROJECT: Optional: the project containingthe source image

    Use this parameter to copy an image from anotherproject.

  • FEATURES: guest OS tags to enable features for VMsthat you create from images

    To add multiple values, use commas to separate values. Set to one ormore of the following values:

    • VIRTIO_SCSI_MULTIQUEUE. Use on local SSD devices as an alternative to NVMe. For more information about images that support SCSI, seeChoosing an interface.

      For Linux images, you can enable multi-queue SCSI on local SSD devices on images with kernel versions 3.17 or later. For Windows images, you can enable multi-queue SCSI on local SSD devices on images with Compute Engine Windows driver version 1.2.

    • WINDOWS. Tag Windows Server custom boot images as Windows images.
    • MULTI_IP_SUBNET. Configure interfaces with a netmask other than/32. For more information about multiple network interfaces and how they work, see Multiple network interfaces overview and examples.
    • UEFI_COMPATIBLE. Boot with UEFI firmware and the following Shielded VM features:
    • GVNIC. Support higher network bandwidths of up to 50 Gbps to 100 Gbps speeds. For more information, see Using Google Virtual NIC.
    • IDPF. Support Intel Infrastructure Data Path Function (IDPF) network interfaces.
    • SEV_CAPABLE orSEV_SNP_CAPABLE. Use these tags if you want to use your image on a Confidential VM instance with AMD Secure Encrypted Virtualization (SEV) or AMD Secure Encrypted Virtualization-Secure Nested Paging (SEV-SNP) support. To check if your kernel supports AMD SEV or AMD SEV-SNP, see Linux kernel details.
    • SEV_LIVE_MIGRATABLE_V2. Use this tag if you want to use your image on a Confidential VM instance that supports live migration on AMD SEV. To check if your kernel supports live migration, see Linux kernel details.
    • TDX_CAPABLE. Use this tag if you want to use your image on a Confidential VM instance with Intel Trust Domain Extensions (TDX) support. To check if your kernel supports Intel TDX, see Linux kernel details.
  • LOCATION: Optional: region or multi-region inwhich to store the image

    For example, specifyus to store the imagein theus multi-region, orus-central1 to store it in theus-central1 region. If you don't make a selection,Compute Engine stores the image in the multi-region closest toyour image's source location.

REST

Use theimages().insert methodwith theguestOsFeatures flag to create a new custom image from anexisting custom image.

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images{ "name": "IMAGE_NAME", "sourceImage": "(projects/IMAGE_PROJECT)/global/images/SOURCE_IMAGE", ("storageLocations": "LOCATION",) "guestOsFeatures": [  {   "type": "FEATURES"  } ]}

Replace the following:

  • PROJECT_ID: the ID of the project in which tocreate the new image
  • IMAGE_NAME: a name for the new image
  • IMAGE_PROJECT: Optional: the project containingthe source image

    Use this parameter to copy an image from anotherproject.

  • SOURCE_IMAGE: the image to base the new image on

  • LOCATION: Optional: a region or multi-region inwhich to store the image

    For example, specifyus to store the image intheus multi-region, orus-central1 to store it in theus-central1region. If you don't make a selection, Compute Engine stores theimage in the multi-region closest to your image's source location.

  • FEATURES: guest OS tags to enable features for VMsthat you create from images

    To add multiple values, use commas to separate values. Set to one ormore of the following values:

    • VIRTIO_SCSI_MULTIQUEUE. Use on local SSD devices as an alternative to NVMe. For more information about images that support SCSI, seeChoosing an interface.

      For Linux images, you can enable multi-queue SCSI on local SSD devices on images with kernel versions 3.17 or later. For Windows images, you can enable multi-queue SCSI on local SSD devices on images with Compute Engine Windows driver version 1.2.

    • WINDOWS. Tag Windows Server custom boot images as Windows images.
    • MULTI_IP_SUBNET. Configure interfaces with a netmask other than/32. For more information about multiple network interfaces and how they work, see Multiple network interfaces overview and examples.
    • UEFI_COMPATIBLE. Boot with UEFI firmware and the following Shielded VM features:
    • GVNIC. Support higher network bandwidths of up to 50 Gbps to 100 Gbps speeds. For more information, see Using Google Virtual NIC.
    • IDPF. Support Intel Infrastructure Data Path Function (IDPF) network interfaces.
    • SEV_CAPABLE orSEV_SNP_CAPABLE. Use these tags if you want to use your image on a Confidential VM instance with AMD Secure Encrypted Virtualization (SEV) or AMD Secure Encrypted Virtualization-Secure Nested Paging (SEV-SNP) support. To check if your kernel supports AMD SEV or AMD SEV-SNP, see Linux kernel details.
    • SEV_LIVE_MIGRATABLE_V2. Use this tag if you want to use your image on a Confidential VM instance that supports live migration on AMD SEV. To check if your kernel supports live migration, see Linux kernel details.
    • TDX_CAPABLE. Use this tag if you want to use your image on a Confidential VM instance with Intel Trust Domain Extensions (TDX) support. To check if your kernel supports Intel TDX, see Linux kernel details.

Avoid sensitive information in UEFI variables

Unified Extensible Firmware Interface (UEFI) variables are key-value pair variablesused by the UEFI firmware during boot time to boot the operating system of a VM.Unlike physical machines, where the variables are stored on a hardware chip,Compute Engine virtualizes storage of these variables. As such, inmany operating systems, all applications and users can reach these variables andaccess this information.

Because of this reason, Google strongly recommends that you don't write or storesensitive or personal identifiable information such as passwords or private keysto UEFI variables.

Considerations for Arm images

Google offers theA4X, C4A, and Tau T2Amachine series, which run on Arm CPU platforms. You can start a VM with one ofthese machine series and then use that source VM to create an Arm image. Theprocess for creating a custom Arm image is identical to creating an x86 image.

To help your users differentiate between Arm and x86 images, Arm images willhave anarchitecture field set toARM64. Possible values for thisfield are:

  • ARCHITECTURE_UNSPECIFIED
  • X86_64
  • ARM64

Image users can then filter on this field to find x86 or Arm-based images.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.