[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Container infrastructure](index.md) > Configuring data output from a Docker container to a serial port

# Configuring data output from a Docker container to a serial port

To create a [VM](../../compute/concepts/vm.md) from an [image](../../compute/concepts/image.md), such as a [Container Optimized Image](../../cos/concepts/index.md), and set up a redirect of the application output stream to the VM's [serial port](../../compute/concepts/serial-console.md):

1. [Get your cloud ready](#before-you-begin).
1. [Create a VM specification file](#prepare-specification-vm).
1. [Create a Docker container specification file](#prepare-specification-docker).
1. [Get the ID of the image for creating the VM](#get-id).
1. [Create your VM](#create-vm).
1. [Check the result](#check-result).

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

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

If the required [Docker image](../../container-registry/concepts/docker-image.md) has been pushed to [Container Registry](../../container-registry/index.md), create a [service account](../../iam/operations/sa/create.md) with the [container-registry.images.puller](../../container-registry/security/index.md#choosing-roles) role for the [registry](../../container-registry/concepts/registry.md) in use. A Container Optimized Image VM will pull the Docker image from the registry under this account.

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.

If you do not have a [network](../../vpc/operations/network-create.md) or [subnet](../../vpc/operations/subnet-create.md), create them.

### 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 using a dynamic or static [external IP address](../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md)).

## Create a VM specification file {#prepare-specification-vm}

{% list tabs group=instructions %}

- CLI {#cli}

  Create a VM specification file named `cloud-config-ports.yaml` and populate it with the following data:

  ```yaml
  #cloud-config
  runcmd:
  - [ sudo, chmod, 666, /dev/ttyS1]
  users:
  - name: <username>
    groups: sudo
    shell: /bin/bash
    sudo: 'ALL=(ALL) NOPASSWD:ALL'
    ssh_authorized_keys:
    - <public_SSH_key_for_connecting_to_VM>
  ```

  In the file configuration, set the username and specify the public part of the [SSH key](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) required to connect to the VM. You will need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.

{% endlist %}

## Create a Docker container spec file {#prepare-specification-docker}

{% list tabs group=instructions %}

- CLI {#cli}

  Create the specification for a Docker container as a file named `container-spec-ports.yaml` and populate it with the following data:

  ```yaml
  spec:
  containers:
  - image: ubuntu
    name: app
    command: ["/bin/bash", "-c", "sleep 30 && echo 'Hello World!' > /dev/ttyS1"]
    securityContext:
      privileged: true
      stdin: false
      tty: false
      volumeMounts:
      - mountPath: /dev/ttyS1
        name: log-port
    restartPolicy: Always
    volumes:
    - name: log-port
      hostPath:
        path: /dev/ttyS1
  ```

  1. Create a VM with multiple [disks](../../compute/concepts/disk.md).
     1. Get the ID of the image for creating the VM:

        {% list tabs group=programming_language %}

        - Bash {#bash}

          ```bash
          IMAGE_ID=$(yc compute image get-latest-from-family container-optimized-image --folder-id standard-images --format=json | jq -r .id)
          ```

        - PowerShell {#powershell}

          ```shell script
          > $IMAGE_ID=(yc compute image get-latest-from-family container-optimized-image --folder-id standard-images --format=json | ConvertFrom-Json).id
          ```

        {% endlist %}

     1. Create a VM:

        ```bash
        yc compute instance create \
          --name coi-vm-with-sp \
          --zone ru-central1-a \
          --network-interface subnet-name=<subnet_name>,nat-ip-version=ipv4 \
          --metadata-from-file user-data=cloud-config-ports.yaml,docker-container-declaration=container-spec-ports.yaml \
          --create-boot-disk image-id=$IMAGE_ID \
          --service-account-name <service_account_name>
        ```

        Where:
        * `--name`: VM name.
        * `--zone`: [Availability zone](../../overview/concepts/geo-scope.md).
        * `--network-interface`: VM network settings.
        * `--metadata-from-file`: YAML [metadata](../../compute/concepts/vm-metadata.md) files for creating the VM.

            {% note info %}
            
            The commands [`yc compute instance create`](../../cli/cli-ref/compute/cli-ref/instance/create.md) | [`create-with-container`](../../cli/cli-ref/compute/cli-ref/instance/create-with-container.md) | [`update`](../../cli/cli-ref/compute/cli-ref/instance/update.md) | [`add-metadata`](../../cli/cli-ref/compute/cli-ref/instance/add-metadata.md) support substitution of environment variable values into VM metadata. When you execute a Yandex Cloud CLI command, these values, specified in the `user-data` key in `$<variable_name>` format, will be substituted into the VM metadata from the environment variables of the environment the command is executed in. 
            
            To change such behavior, i.e. to provide a variable name to the VM metadata in `$<variable_name>` format rather than take the variable value from the CLI command runtime environment, use the two-dollar syntax, e.g., `$$<variable_name>`.
            
            For more information, see [Specifics of providing environment variables in metadata via the CLI](../../compute/concepts/metadata/sending-metadata.md#environment-variables).
            
            {% endnote %}
        * `--create-boot-disk`: ID of the image for creating a boot disk from.
        * `--service-account-name`: Name of the service account you created [earlier](#before-you-begin).

        Once created, the VM will appear in the VM list under **Compute Cloud** in the [management console](https://console.yandex.cloud).
     1. Check the result.
        1. In the [management console](https://console.yandex.cloud), navigate to the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) page.
        1. Navigate to **Compute Cloud**.
        1. Click the VM name, `coi-vm-with-sp`.
        1. Under **Serial port**, select the `COM2` port. In a few minutes, the screen will display `Hello world!`.

{% endlist %}

## Get the ID of the image for creating the VM {#get-id}

To get the ID of the latest image to create a VM, run:

{% list tabs group=operating_system %}

- Linux (Bash) {#linux}

  ```bash
  IMAGE_ID=$(yc compute image get-latest-from-family container-optimized-image \
    --folder-id standard-images \
    --format=json | jq -r .id)
  ```

- Windows (PowerShell) {#windows}

  ```shell script
  $IMAGE_ID=(yc compute image get-latest-from-family container-optimized-image `
    --folder-id standard-images `
    --format=json | ConvertFrom-Json).id
  ```

{% endlist %}

## Create a VM {#create-vm}

{% list tabs group=instructions %}

- CLI {#cli}

  Enter a name for the [subnet](../../vpc/operations/subnet-create.md) where you will keep your VM and run:

  ```bash
  yc compute instance create \
    --name coi-vm-with-sp \
    --zone ru-central1-d \
    --network-interface subnet-name=<subnet_name>,nat-ip-version=ipv4 \
    --metadata-from-file user-data=cloud-config-ports.yaml,docker-container-declaration=container-spec-ports.yaml \
    --create-boot-disk image-id=$IMAGE_ID
  ```

  Where:
  * `--name`: VM name.
  * `--zone`: Availability zone.
  * `--network-interface`: VM network settings.
  * `--metadata-from-file`: YAML metadata files for creating the VM.
  * `--create-boot-disk`: ID of the image for creating a boot disk from.

{% endlist %}

Once created, the VM will appear in the VM list under **Compute Cloud** in the [management console](https://console.yandex.cloud).

## Check the result {#check-result}

To check whether you correctly configured data output from the Docker container to the serial port:
1. In the [management console](https://console.yandex.cloud), navigate to the folder page.
1. Navigate to **Compute Cloud**.
1. Click the VM name, `coi-vm-with-sp`.
1. Under **Serial port**, select the `COM2` port. In a few minutes, the screen will display `Hello world!`.

For more information about working with VMs, see [our step-by-step guides](../../compute/operations/index.md).

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

To stop paying for the resources you created:
1. [Delete the VM](../../compute/operations/vm-control/vm-delete.md).
1. If you reserved a public static IP address for the VM, [delete it](../../vpc/operations/address-delete.md).