[Yandex Cloud documentation](../../../index.md) > [Tutorials](../../index.md) > [Basic infrastructure](../../infrastructure/index.md) > Tools > [Running a Docker image on a VM](index.md) > Management console, CLI, and API

# Running a Docker image on a VM using the management console, CLI, and API

To run a [Docker image on a VM](index.md) using a [Yandex Container Registry](../../../container-registry/index.md) registry, complete these steps:

1. [Get your cloud ready](#before-you-begin).
1. [Create a registry in Container Registry](#create-registry).
1. [Create a service account](#create-sa).
1. [Create your Compute Cloud VM](#create-vm).
1. [Build and push the Docker image to Container Registry](#create-image).
1. [Upload the Docker image to the VM](#run).
1. [Check the result](#check-out).

If you no longer need the resources you created, [delete them](#clear-out).


## Get your cloud ready {#before-you-begin}

Sign up for Yandex Cloud and create a [billing account](../../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../../billing/quickstart/index.md) and [link](../../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../../resource-manager/concepts/resources-hierarchy.md).


### Required paid resources {#paid-resources}

The infrastructure support cost includes:
* Fee for a continuously running VM (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for a dynamic or static [public IP address](../../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for storing a Docker image in the registry and outgoing traffic (see [Yandex Container Registry pricing](../../../container-registry/pricing.md)).


### Create an SSH key pair {#create-ssh}

Prepare an SSH key for [VM access](../../../compute/operations/vm-connect/ssh.md).

{% list tabs group=operating_system %}

- Linux/macOS {#linux-macos}

  1. Open the terminal.
  1. Use the `ssh-keygen` command to create a new key:
  
      ```bash
      ssh-keygen -t ed25519 -C "<optional_comment>"
      ```
  
      You can specify an empty string in the `-C` parameter to avoid adding a comment, or you may not specify the `-C` parameter at all: in this case, a default comment will be added.
  
      After running this command, you will be prompted to specify the name and path to the key files, as well as enter the password for the private key. If you only specify the name, the key pair will be created in the current directory. The public key will be saved in a file with the `.pub` extension, while the private key, in a file without extension.
  
      By default, the command prompts you to save the key under the `id_ed25519` name in the following directory: `/home/<username>/.ssh`. If there is already an SSH key named `id_ed25519` in this directory, you may accidentally overwrite it and lose access to the resources it is used in. Therefore, you may want to use unique names for all SSH keys.

- Windows 10/11 {#windows}

  If you do not have [OpenSSH](https://en.wikipedia.org/wiki/OpenSSH) installed yet, follow this [guide](https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui) to install it.
  
  1. Run `cmd.exe` or `powershell.exe` (make sure to update PowerShell before doing so).
  1. Use the `ssh-keygen` command to create a new key:
  
      ```shell
      ssh-keygen -t ed25519 -C "<optional_comment>"
      ```
  
      You can specify an empty string in the `-C` parameter to avoid adding a comment, or you may not specify the `-C` parameter at all: in this case, a default comment will be added.
  
      After running this command, you will be prompted to specify the name and path to the key files, as well as enter the password for the private key. If you only specify the name, the key pair will be created in the current directory. The public key will be saved in a file with the `.pub` extension, while the private key, in a file without extension.
  
      By default, the command prompts you to save the key under the `id_ed25519` name in the following folder: `C:\Users\<username>/.ssh`. If there is already an SSH key named `id_ed25519` in this directory, you may accidentally overwrite it and lose access to the resources it is used in. Therefore, you may want to use unique names for all SSH keys.

- Windows 7/8 {#windows7-8}

  Create keys using the PuTTY app:
  
  1. [Download](https://www.putty.org) and install PuTTY.
  1. Add the folder with PuTTY to the `PATH` variable:
  
      1. Click **Start** and type **Change system environment variables** in the Windows search bar.
      1. Click **Environment Variables...** at the bottom right.
      1. In the window that opens, find the `PATH` parameter and click **Edit**.
      1. Add your folder path to the list.
      1. Click **OK**.
  
  1. Launch the PuTTYgen app.
  1. Select **EdDSA** as the pair type to generate. Click **Generate** and move the cursor in the field above it until key creation is complete.
  
      ![ssh_generate_key](../../../_assets/compute/ssh-putty/ssh_generate_key.png)
  
  1. In **Key passphrase**, enter a strong password. Enter it again in the field below.
  1. Click **Save private key** and save the private key. Do not share its key phrase with anyone.
  1. Click **Save public key** and save the public key to a file named `<key_name>.pub`.

{% endlist %}

{% note warning %}

Store your private key securely, as you will not be able to connect to the VM without it.

{% endnote %}


### Install and configure Docker {#configure-docker}

{% list tabs group=operating_system %}

- Linux {#linux}

    1. Install Docker Engine. Use [this guide](https://docs.docker.com/engine/install/#supported-platforms) to install and run Docker for your operating system.

    1. After the installation is complete, add the current user to the `docker` group:

        ```bash
        sudo groupadd docker
        sudo usermod -aG docker $USER
        newgrp docker
        ```

    For groups to update successfully, you may need to log back into the OS or reboot the computer.

    For information on additional Docker settings in Linux, see [this developer guide](https://docs.docker.com/engine/install/linux-postinstall/).

    If you are working on a device with a GUI, you can also [install](https://docs.docker.com/desktop/install/linux-install/) Docker Desktop for Linux.

- macOS {#macos}

  [Download](https://docs.docker.com/get-docker/) and install the Docker Desktop distribution for macOS. For more information, see [this developer guide](https://docs.docker.com/desktop/install/mac-install/).

- Windows {#windows}

    1. [Download](https://docs.docker.com/get-docker/) and install the Docker Desktop distribution for Windows.

    1. After the installation is complete, add the current user to the `docker-users` group:

        1. Run **Computer Management** as administrator:

            ```powershell
            compmgmt.msc
            ```
        
        1. Expand the **(Local) Computer Management** menu, then go **Utilities** → **Local Users and Groups** → **Groups** and open the `docker-users` group.
        1. Click **Add** and add the required user to the group.
        1. Click **OK**.
    1. Run Docker Desktop and make sure the app's status is `running`.

    For information on additional Docker settings in Windows, see [this developer guide](https://docs.docker.com/desktop/install/windows-install/).

{% endlist %}


## Create a registry in Container Registry {#create-registry}

[Create a registry](../../../container-registry/operations/registry/registry-create.md) in Container Registry.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a registry.
  1. Navigate to **Container Registry**.
  1. Click **Create registry**.
  1. Specify a name for the registry. The naming requirements are as follows:
  
      * Length: between 3 and 63 characters.
      * It can only contain lowercase Latin letters, numbers, and hyphens.
      * It must start with a letter and cannot end with a hyphen.
  
  1. Optionally, under **Automatic scanning**:
  
  
      * Disable **Scan Docker images on push** to skip scanning of Docker images at their upload to the repository.
      * Disable **Scan all Docker images in the registry** or set the scanning frequency.
  
        {% note warning %}
        
        Automatic Docker image scanning makes your registry more secure. The default vulnerability scan settings are consistent with the [Yandex Cloud cloud infrastructure security standard](../../../security/standard/app-security.md#pipeline-recommendations).
        
        {% endnote %}
  
  1. Optionally, add labels.
  1. Click **Create registry**.

- CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../../cli/quickstart.md#install).
  
  The folder used by default is the one specified when [creating](../../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.
  
  1. Make sure that a registry has not been created in the folder yet:
  
      ```bash
      yc container registry list
      ```
  
      Result:
  
      ```text
      +----+------+-----------+
      | ID | NAME | FOLDER ID |
      +----+------+-----------+
      +----+------+-----------+
      ```
  
      If the folder already contains a registry, see [Updating a registry](../../../container-registry/operations/registry/registry-update.md) for info on how you can update it.
  
  1. Create a registry:
  
      * With automated vulnerability scanning:
  
  
          ```bash
          yc container registry create --name my-reg --secure
          ```
  
        {% note warning %}
        
        Automatic Docker image scanning makes your registry more secure. The default vulnerability scan settings are consistent with the [Yandex Cloud cloud infrastructure security standard](../../../security/standard/app-security.md#pipeline-recommendations).
        
        {% endnote %}
  
      * Without automated vulnerability scanning:
  
          ```bash
          yc container registry create --name my-reg
          ```
  
      Result:
  
      ```text
      done
      id: crpd50616s9a********
      folder_id: b1g88tflru0e********
      name: my-reg
      status: ACTIVE
      created_at: "2019-01-09T14:34:06.601Z"
      ```
  
      Follow these registry naming requirements:
  
      * Length: between 3 and 63 characters.
      * It can only contain lowercase Latin letters, numbers, and hyphens.
      * It must start with a letter and cannot end with a hyphen.
  
      The `--name` parameter is optional. You can create a registry without a name and use its ID to access it. The `name` field is user-defined. It is used when listing in the Yandex Cloud CLI and not used in the Docker CLI.
  1. Make sure the registry was created:
  
      ```bash
      yc container registry list
      ```
  
      Result:
  
      ```text
      +----------------------+--------+----------------------+
      |          ID          |  NAME  |      FOLDER ID       |
      +----------------------+--------+----------------------+
      | crpd50616s9a******** | my-reg | b1g88tflru0e******** |
      +----------------------+--------+----------------------+
      ```

- API {#api}

  To create a registry, use the [create](../../../container-registry/api-ref/Registry/create.md) method for the [Registry](../../../container-registry/api-ref/Registry/index.md) resource.

{% endlist %}


## Create a service account {#create-sa}

Create a [service account](../../../iam/concepts/users/service-accounts.md) and assign to it the `container-registry.images.puller` [role](../../../iam/concepts/access-control/roles.md) for the registry you created earlier:

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the relevant folder.
  1. Navigate to **Identity and Access Management**.
  1. Click **Create service account**.
  1. Name the [service account](../../../iam/concepts/users/service-accounts.md): `images-puller`.
  1. Click **Create**.
  1. At the top of the screen, navigate to the **Folder dashboard** tab.
  1. Navigate to **Container Registry**.
  1. Select the registry and click the row with its name.
  1. Navigate to the **Access bindings** tab.
  1. In the top-right corner, click **Assign roles**.
  1. Click ![image](../../../_assets/console-icons/plus.svg) **Select subject** and add the service account by providing its ID.
  1. Click **Add role** and select `container-registry.images.puller`.
  1. Click **Save**.

- CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../../cli/quickstart.md#install).

  1. See the description of the CLI command for creating a service account:

      ```bash
      yc iam service-account create --help
      ```

  1. Create a service account:

      The folder used by default is the one specified when [creating](../../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

      ```bash
      yc iam service-account create --name images-puller
      ```

      Result:

      ```text
      id: ajelabcde12f********
      folder_id: b0g12ga82bcv********
      created_at: "2020-11-30T14:32:18.900092Z"
      name: myservice-acc
      ```

  1. Assign the `container-registry.images.puller` role to the service account:

      ```bash
      yc container registry add-access-binding <registry_name_or_ID> \
        --role container-registry.images.puller \
        --subject serviceAccount:<service_account_ID>
      ```

      Where `--subject` is the ID of the service account getting the role, e.g., `ajelabcde12f********`.

- API {#api}

  1. To create a service account, use the [create](../../../iam/api-ref/ServiceAccount/create.md) REST API method for the [ServiceAccount](../../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/Create](../../../iam/api-ref/grpc/ServiceAccount/create.md) gRPC API call.

  1. To assign the service account a role for the registry, use the [updateAccessBindings](../../../container-registry/api-ref/Registry/updateAccessBindings.md) REST API method for the [Registry](../../../container-registry/api-ref/Registry/index.md) resource or the [RegistryService/UpdateAccessBindings](../../../container-registry/api-ref/grpc/Registry/updateAccessBindings.md) gRPC API call.

{% endlist %}


## Create a Compute Cloud VM {#create-vm}

Create a VM with a public IP address and link the service account you created to it:

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), navigate to the [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) dashboard, click **Create resource**, and select `Virtual machine instance`.
  1. Under **Boot disk image**, select an [image](../../../compute/operations/images-with-pre-installed-software/get-list.md) and a Linux-based OS version.
  1. Under **Location**, select the [availability zone](../../../overview/concepts/geo-scope.md) to create your VM in. If you are not sure which availability zone you need, leave the default selection.
  1. Optionally, under **Disks and file storages**, specify the required boot [disk](../../../compute/concepts/disk.md) [type](../../../compute/concepts/disk.md#disks-types) and size.

      To add a new secondary disk or connect an existing one, click **Add**.

      You can also [create a VM from an existing disk](../../../compute/operations/vm-create/create-from-disks.md).

  1. Under **Network settings**:

      * In the **Subnet** field, select the network and subnet to which you want to connect your VM. If the [network](../../../vpc/concepts/network.md#network) or [subnet](../../../vpc/concepts/network.md#subnet) you need does not exist yet, [create it](../../../vpc/operations/subnet-create.md).
      * In the **Public IP address** field, select a static IP address from the list, or leave `Auto` to assign your VM a random external IP address from the Yandex Cloud pool. If you prefer not to assign a public IP address, select `No address`.
      * Expand **Additional** and enable DDoS protection, if required.

  1. Under **Access**, select **SSH key** and specify the VM access data:

      * In the **Login** field, enter a username. Do not use `root` or other reserved usernames. For operations requiring root privileges, use the `sudo` command.
      * In the **SSH key** field, select the SSH key saved in your [organization user](../../../organization/concepts/membership.md) profile.
        
        If there are no SSH keys in your profile or you want to add a new key:
        
        1. Click **Add key**.
        1. Enter a name for the SSH key.
        1. Select one of the following:
        
            * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
            * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
            * `Generate key`: Automatically create an SSH key pair.
            
              When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
        
        1. Click **Add**.
        
        The system will add the SSH key to your organization user profile. If the organization has [disabled](../../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.

  1. Under **General information**, specify the VM name. The naming requirements are as follows:

      * Length: between 3 and 63 characters.
      * It can only contain lowercase Latin letters, numbers, and hyphens.
      * It must start with a letter and cannot end with a hyphen.

      {% note info %}
      
      The VM name is used to generate an [internal FQDN](../../../compute/concepts/network.md#hostname), which is set only once, when you create the VM. If the internal FQDN is important to you, make sure to choose an appropriate name for your VM.
      
      {% endnote %}

  1. Under **Additional**, select the [service account](../../../iam/concepts/users/service-accounts.md) you created in the previous step.
  1. Click **Create VM**.

- CLI {#cli}

  1. View the description of the CLI command to create a VM:

      ```bash
      yc compute instance create --help
      ```

  1. Prepare a key pair (public and private keys) for SSH access to your VM.
  1. Select in Cloud Marketplace a public [image](../../../compute/operations/images-with-pre-installed-software/get-list.md) based on a Linux OS (for example, [CentOS 7](https://yandex.cloud/en/marketplace/products/yc/centos-7)).

      To get a list of available images using the CLI, run this command:
      
      ```bash
      yc compute image list --folder-id standard-images
      ```
      
      Result:
      
      ```text
      +----------------------+-------------------------------------+--------------------------+----------------------+--------+
      |          ID          |                NAME                 |          FAMILY          |     PRODUCT IDS      | STATUS |
      +----------------------+-------------------------------------+--------------------------+----------------------+--------+
      ...
      | fdvk34al8k5n******** | centos-7-1549279494                 | centos-7                 | dqni65lfhvv2******** | READY  |
      | fdv7ooobjfl3******** | windows-2016-gvlk-1548913814        | windows-2016-gvlk        | dqnnc72gj2is******** | READY  |
      | fdv4f5kv5cvf******** | ubuntu-1604-lts-1549457823          | ubuntu-1604-lts          | dqnnb6dc7640******** | READY  |
      ...
      +----------------------+-------------------------------------+--------------------------+----------------------+--------+
      ```
      
      Where:
      
      * `ID`: Image ID.
      * `NAME`: Image name.
      * `FAMILY`: ID of the [image family](../../../compute/concepts/image.md#family) the image belongs to.
      * `PRODUCT IDS`: IDs of Yandex Cloud Marketplace [products](../../../marketplace/concepts/product.md) associated with the image.
      * `STATUS`: Current status of the image. It may take one of the following values:
      
          * `STATUS_UNSPECIFIED`: Image status is not defined.
          * `CREATING`: Image is being created.
          * `READY`: Image is ready to use.
          * `ERROR`: You cannot use the image due to an issue.
          * `DELETING`: Image is being deleted.

  1. View a list of available subnets:

      ```bash
      yc vpc subnet list
      ```

      Result:

      ```text
      +----------------------+---------------------------+----------------------+----------------+-------------------+-----------------+
      |          ID          |           NAME            |      NETWORK ID      | ROUTE TABLE ID |       ZONE        |      RANGE      |
      +----------------------+---------------------------+----------------------+----------------+-------------------+-----------------+
      | b0c6n43f9lgh******** | default-ru-central1-d     | enpe3m3fa00u******** |                | ru-central1-d     | [10.130.0.0/24] |
      | e2l2da8a20b3******** | default-ru-central1-b     | enpe3m3fa00u******** |                | ru-central1-b     | [10.129.0.0/24] |
      | e9bnlm18l70a******** | default-ru-central1-a     | enpe3m3fa00u******** |                | ru-central1-a     | [10.128.0.0/24] |
      +----------------------+---------------------------+----------------------+----------------+-------------------+-----------------+
      ```

  1. Create a VM in the default folder:

      ```bash
      yc compute instance create \
        --name first-instance \
        --zone ru-central1-b \
        --network-interface subnet-name=default-ru-central1-b,nat-ip-version=ipv4 \
        --create-boot-disk image-folder-id=standard-images,image-family=centos-7 \
        --ssh-key ~/.ssh/id_ed25519.pub
        --service-account-name service-acc
      ```

      Where:

      * `--name`: VM name.

        {% note info %}
        
        The VM name is used to generate an [internal FQDN](../../../compute/concepts/network.md#hostname), which is set only once, when you create the VM. If the internal FQDN is important to you, make sure to choose an appropriate name for your VM.
        
        {% endnote %}

      * `--zone`: Availability zone matching the selected subnet.
      * `subnet-name`: Name of the selected subnet.
      * `image-family`: [Image family](../../../compute/concepts/image.md#family), e.g., `centos-7`. This option allows you to install the latest version of the operating system from the specified image family.
      * Public IP. To create a VM without a public IP address, disable the `nat-ip-version=ipv4` option.
      * `--ssh-key`: Public SSH key path. The VM will automatically create a user named `yc-user` for this key.
      * `--service-account-name`: Name of the service account created in the previous step.

      This will create a VM called `first-instance`.

- API {#api}

  Create a VM using the [Create](../../../compute/api-ref/Instance/create.md) REST API method for the [Instance](../../../compute/api-ref/Instance/index.md) resource:

  1. Prepare a key pair (public and private keys) for SSH access to your VM.
  1. Get a [Yandex Identity and Access Management token](../../../iam/concepts/authorization/iam-token.md) used for authentication in the examples:

      * [Guide](../../../iam/operations/iam-token/create.md) for a Yandex account user.
      * [Guide](../../../iam/operations/iam-token/create-for-sa.md) for a service account.

  1. [Get the ID](../../../resource-manager/operations/folder/get-id.md) of the folder.
  1. Get information about the image to create your VM from (image ID and minimum disk size):

      * If you know the [image family](../../../compute/concepts/image.md#family), get info on the latest image in that family:

          ```bash
          export IAM_TOKEN=CggaATEVAgA...
          export FAMILY=ubuntu-1804
          curl --header "Authorization: Bearer ${IAM_TOKEN}" \
            "https://compute.api.cloud.yandex.net/compute/v1/images:latestByFamily?folderId=standard-images&family=${FAMILY}"
          ```

      * You can get information on the image from the [list of public images](../../../compute/operations/images-with-pre-installed-software/get-list.md).

  1. Get the subnet ID and availability zone ID. Specify the ID of the folder where the subnet was created in your request:

      ```bash
      export IAM_TOKEN=CggaATEVAgA...
      export FOLDER_ID=b1gvmob95yys********
      curl --header "Authorization: Bearer ${IAM_TOKEN}" \
        "https://vpc.api.cloud.yandex.net/vpc/v1/subnets?folderId=${FOLDER_ID}"
      {
        "subnets": [
          {
            "v4CidrBlocks": [
              "10.130.0.0/24"
            ],
          "id": "b0c6n43ftldh********",
          "folderId": "b1gvmob95yys********",
          "createdAt": "2018-09-23T12:15:00Z",
          "name": "default-ru-central1-b",
          "description": "Auto-created default subnet for zone ru-central1-b",
          "networkId": "enpe3m3faglu********",
          "zoneId": "ru-central1-b"
        },
        ...
        ]}
      ```

  1. Create a file containing the body of your VM create request, e.g., `body.json`:

      ```json
      {
        "folderId": "b1gvmob95yys********",
        "name": "instance-demo-no-pwauth",
        "zoneId": "ru-central1-b",
        "platformId": "standard-v3",
        "resourcesSpec": {
          "memory": "2147483648",
          "cores": "2"
        },
        "metadata": {
          "user-data": "#cloud-config\nusers:\n  - name: user\n    groups: sudo\n    shell: /bin/bash\n    sudo: 'ALL=(ALL) NOPASSWD:ALL'\n    ssh_authorized_keys:\n      - ssh-ed25519 AAAAB3N... user@example.com"
        },
        "bootDiskSpec": {
          "diskSpec": {
            "size": "2621440000",
            "imageId": "fd8rc75pn12f********"
          }
        },
        "networkInterfaceSpecs": [
          {
            "subnetId": "b0c6n43ftldh********",
            "primaryV4AddressSpec": {
              "oneToOneNatSpec": {
                "ipVersion": "IPV4"
              }
            }
          }
        ],
        "serviceAccountId": "ajelabcde12f********"
      }
      ```

      Where:

      * `folderId`: Folder ID.
      * `name`: Name the VM will get when created.
      * `zoneId`: Availability zone matching the selected subnet.
      * `platformId`: [Platform](../../../compute/concepts/vm-platforms.md).
      * `resourceSpec`: Resources available to the VM. The values must match the selected platform.
      * `metadata`: In metadata, provide the public key for accessing the VM via SSH. For more information, see [VM metadata](../../../compute/concepts/vm-metadata.md).
      * `bootDiskSpec`: Boot disk settings. Specify the selected image ID and disk size. The disk size must not be less than the minimum value specified in the image info.
      * `networkInterfaceSpecs`: Network settings:

        * `subnetId`: ID of the selected subnet.
        * `primaryV4AddressSpec`: IP address to assign to the VM. To add a [public IP address](../../../vpc/concepts/address.md#public-addresses) to your VM, specify the following:

            ```yaml
            "primaryV4AddressSpec": {
              "oneToOneNatSpec": {
                "ipVersion": "IPV4"
              }
            }
            ```

      * `serviceAccountId`: ID of the service account created in the previous step.

      For more information about the request body format, see the [API reference](../../../compute/api-ref/Instance/create.md).

  1. Create a VM:

      ```bash
      export IAM_TOKEN=CggaATEVAgA...
      curl --request POST \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer ${IAM_TOKEN}" \
        --data '@body.json' \
        https://compute.api.cloud.yandex.net/compute/v1/instances
      ```

{% endlist %}

After creating the VM, [build and upload the Docker image to Container Registry](#create-image). 


## Build and push the Docker image to Container Registry {#create-image}

The example below is for MacOS and Linux. To run it on Windows, [check the details on working with Bash in Microsoft Windows](../../../overview/concepts/console-syntax-guide.md).

1. Open the terminal.
1. To make command execution easier, add the following variables:

    * Username and your VM's public IP to the `${PUBLIC_IP}` variable:

        ```bash
        export PUBLIC_IP=<username>@<VM_public_IP_address>
        ```

    * ID of the previously created registry in `crpc9qeoft23********` format to the `${REGISTRY_ID}` variable:

        ```bash
        export REGISTRY_ID=<registry_ID>
        ```

1. Authenticate as yourself:

    {% list tabs group=registry_auth %}

    - OAuth token {#oauth-token}

      {% note info "OAuth token authentication is deprecated" %}
      
      This authentication method will no longer be supported. Consider using [IAM tokens](../../../iam/concepts/authorization/iam-token.md) or [API keys](../../../iam/concepts/authorization/api-key.md).
      
      {% endnote %}

      1. If you do not have an OAuth token yet, get one by following [this link](https://oauth.yandex.com/authorize?response_type=token&client_id=1a6990aa636648e9b2ef855fa7bec2fb).
      1. Run this command:

          ```bash
          echo <OAuth_token> | docker login --username oauth --password-stdin cr.yandex
          ```

          Result:

          ```text
          Login Succeeded
          ```

    - IAM token {#iam-token}

      {% note info %}

      The IAM token has a short [lifetime](../../../iam/concepts/authorization/iam-token.md#lifetime) of up to 12 hours. This makes it a good method for applications that automatically request an IAM token.

      {% endnote %}

      1. [Get](../../../iam/operations/iam-token/create.md) an IAM token.
      1. Run this command:

          ```bash
          yc iam create-token | docker login --username iam --password-stdin cr.yandex
          ```

          Result:

          ```text
          ...
          Login Succeeded
          ```

    - Docker credential helper {#docker}

      1. If you do not have a CLI profile yet, [create one](../../../cli/quickstart.md#initialize).
      1. Configure Docker to use `docker-credential-yc`:

          ```bash
          yc container registry configure-docker
          ```

          Result:

          ```text
          Credential helper is configured in '/home/<user>/.docker/config.json'
          ```

          The current user’s profile stores the settings.

          {% note warning %}

          The credential helper only works if you use Docker without `sudo`. To learn how to configure Docker to run under the current user without `sudo`, see the [official documentation](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).

          {% endnote %}

      1. Make sure that Docker is configured.

          The following line must appear in the `/home/<user>/.docker/config.json` configuration file:

          ```json
          "cr.yandex": "yc"
          ```

      1. You can now use Docker, for example, to [push Docker images](../../../container-registry/operations/docker-image/docker-image-push.md). You do not need to run the `docker login` command for that.

    {% endlist %}

1. Create a file called Dockerfile:

    ```bash
    touch .dockerfile
    ```

1. Open Dockerfile in a text editor, e.g.:

    ```bash
    nano .dockerfile
    ```

1. Add the lines below to the file:

    ```text
    FROM ubuntu:latest
    CMD echo "Hi, I'm inside"
    ```

1. Build the Docker image:

    ```bash
    docker build . -t cr.yandex/${REGISTRY_ID}/ubuntu:hello -f .dockerfile
    ```

    Result:

    ```text
    ...
    Successfully built b68ee9b6b1af
    Successfully tagged cr.yandex/crpmnjr98tm5********/ubuntu:hello
    ```

1. Push the built Docker image to Container Registry:

    ```bash
    docker push cr.yandex/${REGISTRY_ID}/ubuntu:hello
    ```

    Result:

    ```text
    The push refers to repository [cr.yandex/crpc9qeoft23********/ubuntu]
    cc9d18e90faa: Pushed
    0c2689e3f920: Pushed
    47dde53750b4: Pushed
    hello: digest: sha256:42068479274f1d4c7ea095482430dcba24dcfe8c23ebdf6d32305928******** size: 943
    ```


## Push the Docker image to the VM {#run}

1. [Use SSH to connect](../../../compute/operations/vm-connect/ssh.md#vm-connect) to the VM.
1. On the VM, [install and configure](../../../container-registry/operations/configure-docker.md) Docker.
1. [Authenticate](../../../compute/operations/vm-connect/auth-inside-vm.md#auth-inside-vm) under the service account tied to the machine:

    ```bash
    curl --header Metadata-Flavor:Google 169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token | \
    cut -f1 -d',' | \
    cut -f2 -d':' | \
    tr -d '"' | \
    docker login --username iam --password-stdin cr.yandex
    ```

    Result:

    ```text
    Login Succeeded
    ```

1. To make it easier to run commands, add the ID of the registry you created earlier to the `${REGISTRY_ID}` variable:

    ```bash
    export REGISTRY_ID=<registry_ID>
    ```

1. Download the Docker image to the VM:

    ```bash
    docker pull cr.yandex/${REGISTRY_ID}/ubuntu:hello
    ```

    Result:

    ```text
    hello: Pulling from crpc9qeoft23********/ubuntu
    6a5697faee43: Pulling fs layer
    ba13d3bc422b: Pulling fs layer
    ...
    Digest: sha256:42068479274f1d4c7ea095482430dcba24dcfe8c23ebdf6d32305928********
    Status: Downloaded newer image for cr.yandex/crpc9qeoft23********/ubuntu:hello
    cr.yandex/crpc9qeoft23********/ubuntu:hello
    ```


## Check the result {#check-out}

Run the Docker image on the VM:

```bash
docker run cr.yandex/${REGISTRY_ID}/ubuntu:hello
```

Result:

```text
Hi, I'm inside
```


## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:

1. [Delete](../../../compute/operations/vm-control/vm-delete.md) the VM.
1. [Delete](../../../vpc/operations/address-delete.md) the static public IP address if you reserved one.
1. [Delete the Docker image](../../../container-registry/operations/docker-image/docker-image-delete.md).
1. [Delete](../../../container-registry/operations/registry/registry-delete.md) the registry.

## See also {#see-also}

* [Running a Docker image on a VM using Terraform](terraform.md)