Creating and configuring instances

There are two ways to create and configure Compute Engine instances runningContainer-Optimized OS from Google.

Forsimple scenarios where you want to run a single container on a VM or on eachVM in amanaged instance group,you can specify a container image and optionalconfiguration parameters when you define the instance or instance template.Compute Engine creates the instance with the latest version ofContainer-Optimized OS and launches the specified container when the VMstarts.

Note: The Compute Engine feature that deploys containers on VMs during VM creation is deprecated. Use thedocker run commands in a startup script or use thecloud-init tool to configure and to run containers on your VMs and MIGs. For more information, seeMigrate containers that were deployed on VMs during VM creation.

Foradvanced scenarios where you can deploy multiple containers and configureDocker options usingcloud-init, you can create a Compute Engine instance withyour choice of Container-Optimized OS image, and then proceed to configure the container asneeded.

Creating a simple instance

Use this method to deploy a single container on a VM using the latest version ofContainer-Optimized OS. You can perform this task using the Google Cloud consoleor gcloud CLI.

Console

Note: TheDeploy container option in the Google Cloud console is deprecated. Use the equivalentdocker run command to configure and to run the container.
  1. Go to the VM instances page.

    Go to the VM instances page

  2. ClickCreate instance.

  3. Specify aName for your instance.

  4. In theContainer section, select theDeploy a container image tothis VM instance checkbox.

  5. Specify theContainer image to use.

    • You can specify an image from Container Registry or Artifact Registry.For example:
      • gcr.io/cloud-marketplace/google/nginx1:1.15 selects an NGINX 1.15 container image from Google Cloud Marketplace.
      • us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0selects a samplehello-app image from Artifact Registry.
    • If you use a container image from Docker Hub, always specify thefull Docker image name. For example, specify the following image nameto deploy an Apache container image:docker.io/httpd:2.4.
  6. Optionally, clickAdvanced container options. For more information,seeConfiguring Options to Run Your Container.

  7. ClickCreate to create the instance, boot the instance,and launch the container.

gcloud

Note: Thecreate-with-container gcloud CLI command is deprecated. Use the equivalentdocker run command to configure and to run the container.

To create a basic VM instance, run the following command:

gcloud compute instances create-with-containerinstance-name \    --container-imageimage-name

Replace the following:

  • instance-name: the name for the new instance.
  • image-name: the name of the container image.

For example, the following command creates a new VM instance namednginx-vm, which will launch and run thegcr.io/cloud-marketplace/google/nginx1:1.15container image:

gcloud compute instances create-with-container nginx-vm \    --container-image gcr.io/cloud-marketplace/google/nginx1:1.15

Similarly, you can create a new VM instance namedhello-app whichwill launch and run a sample container in Artifact Registry:

gcloudcomputeinstancescreate-with-containerhello-app\--container-imageus-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

When using a container image from Docker Hub, you must always specify a fullDocker image name. For example, specify the following image name to deployan Apache container image:

docker.io/httpd:2.4

To run a single container on each VM in a managed instance group, specify thecontainer image name when defining the instance template. SeeCreating an instance template with a container imagefor more information.

Creating an instance for advanced scenarios

Use this method to select a specific Container-Optimized OS image, to deploymultiple containers, and to usecloud-init for advanced configuration.

Viewing available images

Container-Optimized OS images are available on Google Cloud console'slist of images with the prefixcos.These are hosted under thecos-cloud project. You can also see allcurrently available releases on command line by running the following command:

gcloud compute images list --project cos-cloud --no-standard-images

The output is similar to the following:

NAME                       PROJECT    FAMILY      DEPRECATED  STATUScos-69-10895-385-0         cos-cloud  cos-69-lts              READYcos-73-11647-534-0         cos-cloud  cos-73-lts              READYcos-77-12371-251-0         cos-cloud  cos-77-lts              READYcos-81-12871-103-0         cos-cloud  cos-81-lts              READYcos-beta-81-12871-44-0     cos-cloud  cos-beta                READYcos-dev-84-13078-0-0       cos-cloud  cos-dev                 READYcos-stable-81-12871-103-0  cos-cloud  cos-stable              READY
Note: The most current Container-Optimized OS images are now available underthe projectcos-cloud, and use the name prefix ofcos. Theseimages are identical to the previous versions of Container-Optimized OS, whichused the name prefixgci and were accessible through thegoogle-containersproject. Thegci images in thegoogle-containers projectare considereddeprecated.
Newer versions of Container-Optimized OS images are nowbeing pushed only to thecos-cloud project; please update yourdevelopment or production workflow to use thecos images incos-cloud to get the latest releases.

Creating an instance

You can create an instance using the Google Cloud console, gcloud CLI, orthe API.

Console

Note: TheDeploy container option in the Google Cloud console is deprecated. Use the equivalentdocker run command to configure and to run the container.

To run a Compute Engine instance with a Container-Optimized OS and Dockerinstalled, do the following:

  1. Open the Compute Engine instance creation page on Google Cloud console.

    Create a new Compute Engine instance

  2. Specify aName for your instance.

  3. In theContainers section, clear theDeploy a container image to this VM instance checkbox. This option isuseful if you want todeploy a single container on the VM.

  4. In theBoot disk section, select a Container-Optimized OS image.

  5. ClickCreate to create and boot the instance.

gcloud

Note: Thecreate-with-container gcloud CLI command is deprecated. Use the equivalentdocker run command to configure and to run the container.

Review theavailable images, then usethe following command to create acos node image instance:

gcloud compute instances createinstance-name \    --imageimage-name \    --image-project cos-cloud \    --zonecompute-zone \    --machine-typemachine-type-name

Replace the following:

  • instance-name: the name of your VM instance.
  • image-name: the name of the Container-Optimized OS image forthe instance, obtained from thelist of available images.From our previous example, we can usecos-beta-81-12871-44-0.
  • compute-zone: thecompute zonefor your instance.
  • machine-type-name: the machine type to use for this new instance.The default type isn1-standard-1.

For example, the following command creates an instanced namedcos-testusing thecos-beta-67-10575-13-0 image:

gcloud compute instances create cos-test \    --image cos-beta-67-10575-13-0 \    --image-project cos-cloud \    --zone us-east1-d \    --machine-type n1-standard-1

You can add the--preemptible flag for one-off, experimental instances.

API

In the API, construct a normal request tocreate an instance,but include a Container-Optimized OS sourceimage.For example:

POST https://compute.googleapis.com/compute/v1/projects/project-id/zones/compute-zone/instances{  'machineType': 'zones/compute-zone/machineTypes/machine-type-name',  'name': 'instance-name',  'networkInterfaces': [    {      'accessConfigs': [        {          'type': 'ONE_TO_ONE_NAT',          'name': 'External NAT'        }      ],      'network': 'global/networks/default'    }  ],  'disks': [    {      'type': 'PERSISTENT',      'boot': true,      'autoDelete': true,      'initializeParams': {        'sourceImage': 'projects/cos-cloud/global/images/image-name'      }    }  ]}

Configuring an instance

In some cases, you might want to do additional configuration when the instanceboots. You can use thecloud-init tool with Container-Optimized OS to applyconfiguration information that you supply in acloud-config format.

Using cloud-init with the Cloud config format

Container-Optimized OS images includecloud-init as a way to configure your instance when it boots up. Thecloud-init toolexpects its configuration in the value of theuser-data key of theinstance metadata. Thecloud-inittool understandsmultiple formats.

Here's an examplecloud-init file showing how to create a user account andcreate a systemd service owned by this user that controls the management of aDocker busybox container:

#cloud-configusers:-name:cloudserviceuid:2000write_files:-path:/etc/systemd/system/cloudservice.servicepermissions:0644owner:rootcontent:|[Unit]Description=Start a simple docker container[Service]ExecStart=/usr/bin/docker run --rm -u 2000 --name=mycloudservice busybox:latest /bin/sleep 3600ExecStop=/usr/bin/docker stop mycloudserviceExecStopPost=/usr/bin/docker rm mycloudserviceruncmd:-systemctl daemon-reload-systemctl start cloudservice.service# Optional once-per-boot setup. For example: mounting a PD.bootcmd:-fsck.ext4 -tvy /dev/[DEVICE_ID]-mkdir -p /mnt/disks/[MNT_DIR]-mount -t ext4 -O ... /dev/[DEVICE_ID] /mnt/disks/[MNT_DIR]
Note: Usingsystemctl enable in theruncmd section of cloud-init will notwork as intended. This is because /etc on Container-Optimized OS is stateless,so commands such assystemctl enable/disable, that modify /etc,won't persist across reboots. SeeDisks and Filesystemfor more information on Container-Optimized OS's filesystem. An alternativetosystemctl enable is to usesystemctl start, as in the example above.cloud-init modules such aswrite_files andruncmd, which are typicallyrun once-per-instance on other distros, are run on every boot on Container-Optimized OS.Note: Theuid option in theusers section is acos node imageextension. This option will not work with other versions of cloud-init. Thisoption explicitly sets the ID for the user and allows you to make surethe ID is consistent between different instances. It's recommendedthat you always set this option. Choose an ID from the [2000, 4999]range to avoid collision with other user accounts.

To create a Container-Optimized OS VM instance that references thiscloud-init file, use the--metadata-from-file command line flag.Assuming thecloud-init file is calledfilename in the currentdirectory, the following command creates a Container-Optimized OS instance andtriggercloud-init by assigning the contents of the file to theuser-datakey in the Instance Metadata:

gcloud compute instances createinstance-name \    --imageimage-name \    --image-project cos-cloud \--metadata-from-file user-data=filename

Replace the following:

  • instance-name: the name of your VM instance.
  • image-name: the name of the Container-Optimized OS image forthe instance. For example,--image=cos-113-18244-85-29.
  • filename: the name of the metadata file.

It is possible to set other metadata flags when creating Container-Optimized OSinstances. Because these properties are simple key-value pairs, you may use the--metadata flag in thegcloud compute instances create command to create theproperties. Also, starting frommilestone 97,you can setmetadata flags in projectmetadata using the--metadata flagin thegcloud compute project-info add-metadata command. Flagsdefined at the instance level will take precedence over flags defined at theproject level.

The previous example can be expanded to collect usage statistics andcrash dump collection with the following command:

gcloud compute instances createinstance-name \    --imageimage-name \    --image-project cos-cloud \--metadata-from-file user-data=filename \    --metadata=cos-metrics-enabled=true

Other metadata flags

Metadata KeyDescriptionDefault Behavior
cos-update-strategySpecifies automatic update behavior. Value could beupdate_enabled,update_disabled, or unset.
If unset, the default auto-update behavior for the milestone will be used.
If enabled, the behavior depends on the release channel:
  • cos-dev and cos-beta: Updates from latest OS version in the corresponding image family
  • LTS milestone and cos-stable: Updates from latest OS version from the same milestone
  • Milestones < 117: Enabled by default
  • Milestones >= 117: Disabled by default
cos-metrics-enabledEnables crash dump collection. Values could be:
true
false (default).
Disabled by default
Caution: Enabling thecos-metrics-enabled setting permits collection of somecrash reports that help Google improve thecos nodeimage. Crash reportscontain a snippet of the most recent portion of the kernel log bufferat the time of the crash, and may contain user orpersonal information, depending on what was happening at the time of the crash.The information is sent to Google directly and is not shared outside of Google.

Connecting to an instance

You can SSH into your VM instance running thecos node image thesame wayyou SSH into other Compute Engine instances.

For example:

gcloud compute sshinstance-name \    --projectproject-id \    --zonecompute-zone

Running startup scripts

You can specify astartup script through themetadata server, using thestartup-script metadata key. You can use theGoogle Cloud CLI, the API, or Google Cloud console to provide astartup script. Refer toRunning Startup Scriptsfor details.

Time synchronization

Beforemilestone 85, Container-Optimized OS usessystemd'ssystemd-timesyncd service to synchronizethe local system clock with a remote Network Time Protocol (NTP) server via theSNTP protocol. The following entries in/etc/systemd/timesyncd.confconfiguration file show commented out default configuration values to help theadministrator make any desired changes:

cat /etc/systemd/timesyncd.conf# comments omitted for brevity[Time]#NTP=#FallbackNTP=metadata.google.internal#RootDistanceMaxSec=5#PollIntervalMinSec=32#PollIntervalMaxSec=2048

So the maximum acceptable root distance is 5 seconds and the minimum andmaximum poll intervals for NTP messages are 32 and 2048 seconds respectively.

Starting from milestone 85, Container-Optimized OS useschronyd service to synchronizethe local system clock with a remote Network Time Protocol (NTP) server via theNTP protocol. The following entries in the/etc/chrony/chrony.confconfiguration file show commented out default configuration values to help theadministrator make any desired changes:

cat /etc/chrony/chrony.conf# Use custom NTP serversserver metadata.google.internal prefer iburst# Record the rate at which the system clock gains/losses time.driftfile /var/lib/chrony/drift# Allow the system clock to be stepped in the first three updates# if its offset is larger than 1 second.makestep 1.0 3# Enable kernel synchronization of the real-time clock (RTC).rtcsync

The NTP server is set frometh0's DHCP response, which is usually theCompute Engine's metadata server:

networkctl status eth0 | grep NTP             NTP: 169.254.169.254

Changing the time zone

The default time zone of Container-Optimized OS from Google is UTC0. Create a symbolic linkto your desired time zone as in the following example:

sudo rm /etc/localtimesudo ln -s /usr/share/zoneinfo/US/Pacific /etc/localtime

Note that/etc is stateless, so the time zone will be reset to the default(UTC0) every reboot.

Enabling or disabling automatic updates

There are two ways to enable or disable automatic updates. The preferred methodis to set thecos-update-strategy instance metadata key toupdate_enabled orupdate_disabled, respectively. For example:

gcloud compute instances createinstance-name \    --imageimage-name \    --image-project cos-cloud \--metadata cos-update-strategy=update_disabled

Starting frommilestone 97,you can also disable or enable automatic updates in project metadata:

gcloud compute project-info add-metadata \--metadata cos-update-strategy=update_disabled
Note: Metadata flags defined at instance level takes precedence over metadata flags defined at project level.

You can also disable automatic updates on a running instance withsystemctl:

sudo systemctl stop update-enginesudo systemctl mask update-engine

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-11-24 UTC.