[Yandex Cloud documentation](../../index.md) > [Yandex Serverless Containers](../index.md) > [Getting started](index.md) > Creating a container

# Getting started with Serverless Containers

In this tutorial, you will [prepare](#prepare) a [Docker image](../../container-registry/concepts/docker-image.md) for a container in Yandex Container Registry and [add](#deploy) it to Serverless Containers.

## Prepare a Docker image for a container {#prepare}

A Docker image is an executable package that contains everything you need to run an application: code, runtime environment, libraries, environment variables, and configuration files.

The application must get the number of the port to receive requests at from the `PORT` environment variable. The variable value is set by the service automatically.

To prepare a container's Docker image:
1. [Create a registry](../../container-registry/operations/registry/registry-create.md) in Yandex Container Registry.
1. [Create and build](../../container-registry/operations/docker-image/docker-image-create.md) a Docker image based on [Dockerfile](https://docs.docker.com/engine/reference/builder/).
1. [Push](../../container-registry/operations/docker-image/docker-image-push.md) the Docker image to the registry.

### App and Dockerfile examples {#examples}

{% list tabs group=programming_language %}

- Node.js {#node}

    **index.js**

    ```js
    const express = require('express');

    const app = express();
    app.use(express.urlencoded({ extended: true }));
    app.use(express.json());

    app.get("/hello", (req, res) => {
        var ip = req.headers['x-forwarded-for']
        console.log(`Request from ${ip}`);
        return res.send("Hello!");
    });

    app.listen(process.env.PORT, () => {
        console.log(`App listening at port ${process.env.PORT}`);
    });
    ```

    **Dockerfile**

    ```dockerfile
    FROM node:16-slim

    WORKDIR /app
    RUN npm install express
    COPY ./index.js .

    CMD [ "node", "index.js" ]
    ```

- Python {#python}

    **index.py**

    ```python
    import os
    from sanic import Sanic
    from sanic.response import text

    app = Sanic(__name__)

    @app.after_server_start
    async def after_server_start(app, loop):
        print(f"App listening at port {os.environ['PORT']}")

    @app.route("/hello")
    async def hello(request):
        ip = request.headers["X-Forwarded-For"]
        print(f"Request from {ip}")
        return text("Hello!")

    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=int(os.environ['PORT']), motd=False, access_log=False)
    ```

    **Dockerfile**

    ```dockerfile
    FROM python:3.10-slim

    WORKDIR /app
    RUN pip install --no-cache-dir --prefer-binary sanic
    COPY ./index.py .

    CMD [ "python", "index.py" ]
    ```

- Go {#go}

    **index.go**

    ```golang
    package main

    import (
        "fmt"
        "net/http"
        "os"
    )

    func main() {
        portStr := os.Getenv("PORT")
        fmt.Printf("App listening at port %s\n", portStr)
        http.Handle("/hello", hwHandler{})
        http.ListenAndServe(":"+portStr, nil)
    }

    type hwHandler struct{}

    func (hwHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
        ip := request.Header.Get("X-Forwarded-For")
        fmt.Printf("Request from %s\n", ip)
        writer.WriteHeader(200)
        _, _ = writer.Write([]byte("Hello!"))
    }
    ```

    **Dockerfile**

    ```dockerfile
    FROM golang:latest AS build

    WORKDIR /app
    ADD index.go .
    RUN GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o server-app *.go

    FROM scratch
    COPY --from=build /app/server-app /server-app

    ENTRYPOINT ["/server-app"]
    ```

{% endlist %}

## Add the image to Serverless Containers {#deploy}

### Create a container {#create-container}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create a [container](../concepts/container.md).
  1. Navigate to **Serverless Containers**.
  1. Click **Create container**.
  1. Enter a name and description for the container. The name format is 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. Click **Create**.

- 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.

  To create a [container](../concepts/container.md), run this command:

  ```bash
  yc serverless container create --name <container_name>
  ```

  Result:

  ```text
  id: bba3fva6ka5g********
  folder_id: b1gqvft7kjk3********
  created_at: "2021-07-09T14:49:00.891Z"
  name: my-beta-container
  url: https://bba3fva6ka5g********.containers.yandexcloud.net/
  status: ACTIVE
  ```

- Terraform {#tf}

  With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
  
  Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.
  
  For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../terraform/index.md).

  If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
  
  
  To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

  To create a [container](../concepts/container.md) and its [revision](../operations/manage-revision.md):

  {% note info %}

  If a [registry](../../container-registry/concepts/registry.md) or [repository](../../container-registry/concepts/repository.md) containing the Docker image is not [public](../../container-registry/qa/index.md#public-registry), you need to specify in the revision settings a [service account](../../iam/concepts/users/service-accounts.md) with Docker image pull [permissions](../../iam/operations/sa/assign-role-for-sa.md), such as the `container-registry.images.puller` role for the folder or registry containing the Docker image.
  
  If a service account is specified in the revision settings, the user or service account creating the revision must have the `iam.serviceAccounts.user` role. This role validates permission to use the service account.

  {% endnote %}

  1. In the configuration file, describe the resources you want to create:
     * `name`: Container name. This is a required setting. Follow these 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.

     * `memory`: Amount of memory allocated to the container, in MB. The default value is 128 MB.
     * `service_account_id`: [Service account](../../iam/concepts/users/service-accounts.md) ID.
     * `url`: URL of the [Docker image](../../container-registry/concepts/docker-image.md) in [Yandex Container Registry](../../container-registry/index.md).

     >Here is an example of the configuration file structure:
     >
     >```hcl
     >resource "yandex_serverless_container" "test-container" {
     >  name               = "<container_name>"
     >  memory             = <memory_size>
     >  service_account_id = "<service_account_ID>"
     >  image {
     >    url = "<Docker_image_URL>"
     >  }
     >}
     >```

     For more on the properties of the `yandex_serverless_container` resource, see [this provider guide](../../terraform/resources/serverless_container.md).
  1. Make sure the configuration files are correct.
     1. In the terminal, navigate to the directory where you created your configuration file.
     1. Run a check using this command:

        ```bash
        terraform plan
        ```

     If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors.
  1. Deploy the cloud resources.
     1. If the configuration is correct, run this command:

        ```bash
        terraform apply
        ```

     1. Confirm creating the resources by typing `yes` and pressing **Enter**.

        This will create all the resources you need in the specified [folder](../../resource-manager/concepts/resources-hierarchy.md#folder). You can check the new resources and their settings using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/index.md) command:

        ```bash
        yc serverless container list
        ```

- API {#api}

  To create a [container](../concepts/container.md), use the [create](../containers/api-ref/Container/create.md) REST API method for the [Container](../containers/api-ref/Container/index.md) resource or the [ContainerService/Create](../containers/api-ref/grpc/Container/create.md) gRPC API call.

{% endlist %}

### Create a container revision {#create-revision}

If a [registry](../../container-registry/concepts/registry.md) or [repository](../../container-registry/concepts/repository.md) containing the Docker image is not [public](../../container-registry/qa/index.md#public-registry), you need to specify in the revision settings a [service account](../../iam/concepts/users/service-accounts.md) with Docker image pull [permissions](../../iam/operations/sa/assign-role-for-sa.md), such as the `container-registry.images.puller` role for the folder or registry containing the Docker image.

If a service account is specified in the revision settings, the user or service account creating the revision must have the `iam.serviceAccounts.user` role. This role validates permission to use the service account.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) with your [container](../concepts/container.md).
  1. Navigate to **Serverless Containers**.
  1. Select the container whose [revision](../concepts/container.md#revision) you want to create.
  1. Navigate to the **Editor** tab.
  1. Under **Image settings**:
      * Specify the Yandex Container Registry Docker image URL.
      * Additionally specify the revision settings as required:
          * **Command**: Commands the container will run when started. It matches the `ENTRYPOINT` instruction in the Dockerfile.
          * **Arguments**: Matches the `CMD` instruction in the Dockerfile. Specify arguments in `key = value` format. If you do not specify this parameter, the default `CMD` value from the Docker image will be used.

              You can provide multiple arguments to a container. To do this, click **Add**.

          * **Working directory**: Allows you to change the working directory of the container. It matches the `WORKDIR` instruction in the Dockerfile. We recommend setting absolute paths to directories.

  1. Click **Create revision**.

- CLI {#cli}

  To create a [container](../concepts/container.md) [revision](../concepts/container.md#revision), run this command:

  ```bash
  yc serverless container revision deploy \
    --container-name <container_name> \
    --image <Docker_image_URL> \
    --cores 1 \
    --memory 1GB \
    --execution-timeout 30s \
    --service-account-id <service_account_ID> \
    --command '<command_1>','<command_2>' \
    --args '<key_1=value_1>','<key_2=value_2>'
  ```


  Where:
  * `--cores`: Number of cores available to the container.
  * `--memory`: Required memory. The default value is 128 MB.
  * `--execution-timeout`: Timeout. The default value is 3 seconds.
  * `--service-account-id`: [ID of the service account](../../iam/operations/sa/get-id.md) with Docker image pull permissions.
  * `--command`: Commands the container will run when started. Separate them by commas. It matches the `ENTRYPOINT` instruction in the Dockerfile.
  * `--args`: Arguments matching the `CMD` instruction in the Dockerfile. Specify them in `key = value` format separated by commas. If you skip this setting, the default `CMD` value from the Docker image will be used.

  Result:

  ```text
  id: bbajn5q2d74c********
  container_id: bba3fva6ka5g********
  created_at: "2021-07-09T15:04:55.135Z"
  image:
    image_url: cr.yandex/crpd3cicopk7********/test-container:latest
    image_digest: sha256:de8e1dce7ceceeafaae122f7670084a1119c961cd9ea1795eae92bd********
  resources:
    memory: "1073741824"
    cores: "1"
  execution_timeout: 3s
  service_account_id: ajeqnasj95o7********
  status: ACTIVE
  ```

- Terraform {#tf}

  With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
  
  Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.
  
  For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../terraform/index.md).

  If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
  
  
  To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

  In Terraform, each update to the resource settings creates a new [revision](../concepts/container.md#revision).

  To create a revision:
  1. Update the `yandex_serverless_container` resource settings in the configuration file:

     ```hcl
     resource "yandex_serverless_container" "test-container" {
       name               = "<container_name>"
       cores              = "<number_of_cores>"
       memory             = "<memory_size>"
       service_account_id = "<service_account_ID>"
       image {
         url      = "<Docker_image_URL>"
         command  = ["<command_1>","<command_2>"]
         args     = ["<key_1=value_1>","key_2=value_2"]
         work_dir = "<working_directory>"
       }
     }
     ```

     Where:

     * `cores`: Number of cores available to the container.
     * `memory`: Required memory. The default value is 128 MB.
     * `command`: Commands the container will run when started. Separate them by commas. It matches the `ENTRYPOINT` instruction in the Dockerfile.
     * `args`: Arguments matching the `CMD` instruction in the Dockerfile. Specify them in `key = value` format separated by commas. If you skip this setting, the default CMD value from the Docker image will be used.
     * `work_dir`: Allows you to change the working directory of the container. It matches the `WORKDIR` instruction in the Dockerfile. We recommend setting absolute paths to directories.

     For more on the properties of the `yandex_serverless_container` resource, see [this provider guide](../../terraform/resources/serverless_container.md).

  1. Create the resources:

     1. In the terminal, navigate to the configuration file directory.
     1. Make sure the configuration is correct using this command:
     
        ```bash
        terraform validate
        ```
     
        If the configuration is valid, you will get this message:
     
        ```bash
        Success! The configuration is valid.
        ```
     
     1. Run this command:
     
        ```bash
        terraform plan
        ```
     
        You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
     1. Apply the configuration changes:
     
        ```bash
        terraform apply
        ```
     
     1. Type `yes` and press **Enter** to confirm the changes.

     This will create the revision. You can check the new revision using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/index.md) command:

     ```bash
     yc serverless container revision list
     ```

- API {#api}

  To create a [container](../concepts/container.md) [revision](../concepts/container.md#revision), use the [deployRevision](../containers/api-ref/Container/deployRevision.md) REST API method for the [Container](../containers/api-ref/Container/index.md) resource or the [ContainerService/DeployRevision](../containers/api-ref/grpc/Container/deployRevision.md) gRPC API call.

{% endlist %}

## Invoke the container {#invoke}

After creating the container, you will get the invocation link. Here is how you can [retrieve it](../operations/invoke.md#link). Make an HTTPS request by sending an [IAM token](../../iam/concepts/authorization/iam-token.md) in the `Authorization` header:

```bash
curl \
  --header "Authorization: Bearer $(yc iam create-token)" \
  https://bba3fva6ka5g********.containers.yandexcloud.net/hello
```

Result:

```text
Hello!
```

## What's next {#whats-next}

* Read about the [service concepts](../concepts/invoke.md).