Tutorial: Create a Snowflake Native App with Snowpark Container Services

Introduction

This tutorial describes how to create a Snowflake Native App with Snowpark Container Services. A Snowflake Native App with Snowpark Container Services is a Snowflake Native App that runs container workloads in Snowflake. Snowflake Native Apps with Snowpark Container Services can run any containerized services, while leveraging all of the features of the Snowflake Native App Framework, including security, logging, shared data content and application logic.

This tutorial uses both Snowflake CLI and Snowsight to perform the required tasks.

What you will learn

In this tutorial, you will learn how to:

  • Use Snowflake CLI to initialize a Snowflake Native App with Snowpark Container Services project.

  • Build a Docker image for an app.

  • Create the application package and required application files for a Snowflake Native App with Snowpark Container Services.

  • Test a Snowflake Native App with Snowpark Container Services by calling the service function within the container.

Prerequisites

To perform this tutorial, you must meet the following prerequisites:

  • Access to a Snowflake account that supports Snowpark Container Services.

  • You must be able to use the ACCOUNTADMIN role to create the role used in this tutorial and grant the required privileges to that role.

  • You must have Snowflake CLI version 2.4.0 or greater installed on your local machine.

  • You must have Docker Desktop installed on your local machine.

Set up a role for this tutorial

This tutorial walks you through the process of creating a Snowflake Native App with Snowpark Container Services using the tutorial_role role. Before working through this tutorial, a Snowflake user with the ACCOUNTADMIN role must perform the following steps to configure this role.

To create and set up the tutorial_role role, do the following:

  1. To create the tutorial_role role, run the following command:

    CREATE ROLE tutorial_role;
    
    Copy
  2. To grant the tutorial_role to the Snowflake user who will perform the tutorial, run the following command:

    GRANT ROLE tutorial_role TO USER <user_name>;
    
    Copy

    Where:

    user_name

    Specifies the name of the user who will perform the tutorial.

  3. To grant the privileges required to create and use the Snowflake objects required by a container app, run the following commands:

    GRANT CREATE INTEGRATION ON ACCOUNT TO ROLE tutorial_role;
    GRANT CREATE WAREHOUSE ON ACCOUNT TO ROLE tutorial_role;
    GRANT CREATE DATABASE ON ACCOUNT TO ROLE tutorial_role;
    GRANT CREATE APPLICATION PACKAGE ON ACCOUNT TO ROLE tutorial_role;
    GRANT CREATE APPLICATION ON ACCOUNT TO ROLE tutorial_role;
    GRANT CREATE COMPUTE POOL ON ACCOUNT TO ROLE tutorial_role WITH GRANT OPTION;
    GRANT BIND SERVICE ENDPOINT ON ACCOUNT TO ROLE tutorial_role WITH GRANT OPTION;
    
    Copy

After performing the tasks in this section, the user that has the tutorial_role role granted to their account has the permissions to create all of the Snowflake objects required to create a Snowflake Native App with Snowpark Container Services. We will use this role through the rest of this tutorial.

In a real-world situation, a provider may need similar privileges or access to existing objects to develop an app with containers, including a compute pool, warehouse, and database.

Create the required objects in your account

In this section, you will create some Snowflake objects required by a Snowflake Native App with Snowpark Container Services.

Set up your Snowflake CLI connection

The commands you will run this tutorial assume that you have configured Snowflake CLI to connect by default to the account where you are developing the app. If this account is not set by default, you can use the -c command line argument to specify a different named connection, for example:

snow sql -q "SELECT 1" -c connection_name
Copy

Create a warehouse and image repository

To create the required objects, perform the following either through Snowsight or Snowflake CLI.

  1. To set the current context in Snowsight to use the tutorial_role role, run the following command:

    USE ROLE tutorial_role;
    
    Copy

    If you are using Snowflake CLI, you can use --role tutorial_role instead.

  2. To create a warehouse for the Snowflake Native App with Snowpark Container Services, run the following command:

    CREATE OR REPLACE WAREHOUSE tutorial_warehouse WITH
      WAREHOUSE_SIZE = 'X-SMALL'
      AUTO_SUSPEND = 180
      AUTO_RESUME = true
      INITIALLY_SUSPENDED = false;
    
    Copy

    A warehouse is required by the Snowflake Native App to run SQL commands and stored procedures.

  3. To create the image repository used to store the container, run the following command:

    CREATE DATABASE tutorial_image_database;
    CREATE SCHEMA tutorial_image_schema;
    CREATE IMAGE REPOSITORY tutorial_image_repo;
    
    Copy

In this section, you created a warehouse that will be used to execute queries for the app you will create, as well as an image repository to host container images.

In the next section you will create an image for the container and upload it to the image repository you created above.

Build an image for a Snowpark Container Services service

In this section, you will build a Docker image and upload it to the image repository you created in the previous section.

Create a project directory

The source code for your app exists in the local file system and can be checked into version control, if desired. We’ll start by using Snowflake CLI to bootstrap a Native Apps project; then, we’ll build the image for our container service in a subfolder.

  1. On your local file system, run the following command to create a folder named na-spcs-tutorial:

    snow app init na-spcs-tutorial
    
    Copy

    Note

    You will add additional files and subfolders to this folder and edit the files this command created in later subsections.

    Note

    Run the snow app init --help to see other templates for setting up a Snowflake Native App development environment.

  2. Create a folder called service inside the na-spcs-tutorial folder. This folder contains the source code for the container-based service we are about to build and publish to Snowflake.

  3. To obtain the Docker files required for the tutorial, download the zip file to your local file system.

  4. Unzip the contents to the na-spcs-tutorial/service folder. This folder should container the following files:

    • echo_service.py

    • Dockerfile

    • templates/basic_ui.html

    • echo_spec.yaml

  5. Open a terminal window, and change to this directory.

Build a Docker image and upload it to the container

To build a Docker image and upload it to the image repository, do the following:

  1. Run the following Docker CLI command. Note that you must specify the current working directory (.) in the command:

    docker build --rm --platform linux/amd64 -t my_echo_service_image:tutorial .
    
    Copy

    This command performs the following:

    • Builds a Docker image using the Docker file included in the zip file that you downloaded

    • Names the image my_echo_service_image

    • Applies the tutorial tag to the image.

  2. To identify the URL of the image repository you created in a previous section, run the following command:

    REPO_URL=$(snow spcs image-repository url tutorial_image_database.tutorial_image_schema.tutorial_image_repo --role tutorial_role)
    echo $REPO_URL
    
    Copy

    The URL of the image repository is captured in the $REPO_URL variable, then printed to the console. You will use this value in the next step.

  3. To create a tag for the image that includes the image URL, run the following Docker CLI command:

    docker tag <image_name> <image_url>/<image_name>
    
    Copy

    This command requires two parameters:

    • <image_name> Specifies the name of the image and tag.

    • <image_url>/<image_name> Specifies the URL of the image repository where the image is uploaded and the image name and tag where it should be stored in the remote repository.

    For this tutorial, use $REPO_URL and my_echo_service_image:tutorial:

    docker tag my_echo_service_image:tutorial $REPO_URL/my_echo_service_image:tutorial
    
    Copy
  4. To authenticate with the Snowflake registry, run the following Snowflake CLI command:

    snow spcs image-registry login [-c connection_name]
    
    Copy

    This command loads necessary credentials required for the Docker CLI to use the image repositories in your Snowflake account. You must specify the connection name, if you are not using the default.

    The message Login Succeeded displays if everything was successful.

  5. To upload the Docker image to the image repository, run the following docker push command:

    docker push $REPO_URL/<image_name>
    
    Copy

    Using the same value as <image_name> from previous steps, this command is:

    docker push $REPO_URL/my_echo_service_image:tutorial
    
    Copy
  6. Confirm the image was uploaded successfully by running the following command:

    snow spcs image-repository list-images tutorial_image_database.tutorial_image_schema.tutorial_image_repo --role tutorial_role
    
    Copy

In this section, you created a Docker image containing the echo service and pushed it to the tutorial_repository image repository you created earlier in the tutorial.

In the next section, you will create an application package that uses this image.

Develop your Snowflake Native App

In this section, you will create the following files:

Project Definition file

A YAML file that contains information about the Snowflake object(s) that you want to create. This file is called snowflake.yml and is used by Snowflake CLI to deploy the application package and object into your account.

Manifest file

A YAML file that contains basic configuration and callback information about the application. This file is called manifest.yml.

Setup Script

An SQL script that runs automatically when a consumer installs an application in their account. This file can be called whatever you like, as long as it is referenced by your manifest.

The first file is used by Snowflake CLI, while the latter two are required by the Snowflake Native App Framework.

You will learn more about these files, and their contents, throughout this tutorial. You will also create a readme file that is useful when viewing and publishing your application in later sections of this tutorial.

Create the manifest file for the application package

To create the required manifest file for the application package, do the following:

  1. Modify na-spcs-tutorial/app/manifest.yml to look like the following:

    manifest_version: 1
    
    artifacts:
       setup_script: setup_script.sql
       readme: README.md
       container_services:
          images:
          - /tutorial_image_database/tutorial_image_schema/tutorial_image_repo/my_echo_service_image:tutorial
    
    privileges:
    - BIND SERVICE ENDPOINT:
         description: "A service that can respond to requests from public endpoints."
    - CREATE COMPUTE POOL:
         description: "Permission to create compute pools for running services"
    
    Copy

    This example includes the following:

    • The artifacts property specifies the locations of resources required by an app with containers, including the location of the Docker image you created in a previous step, as well as the project README that will be visible in Snowsight.

    • The privileges property allows a service to respond to public requests as well as to create its own compute pool. These properties are required for instantiating our service in the next step of the tutorial.

Create the setup script for the application package

To create the required setup script for the application package, do the following:

  1. Modify the na-spcs-tutorial/app/setup_script.sql file to include the following:

    CREATE APPLICATION ROLE IF NOT EXISTS app_user;
    
    CREATE SCHEMA IF NOT EXISTS core;
    GRANT USAGE ON SCHEMA core TO APPLICATION ROLE app_user;
    
    CREATE OR ALTER VERSIONED SCHEMA app_public;
    GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_user;
    
    CREATE OR REPLACE PROCEDURE app_public.start_app()
       RETURNS string
       LANGUAGE sql
       AS
    $$
    BEGIN
       -- account-level compute pool object prefixed with app name to prevent clashes
       LET pool_name := (SELECT CURRENT_DATABASE()) || '_compute_pool';
    
       CREATE COMPUTE POOL IF NOT EXISTS IDENTIFIER(:pool_name)
          MIN_NODES = 1
          MAX_NODES = 1
          INSTANCE_FAMILY = CPU_X64_XS
          AUTO_RESUME = true;
    
       CREATE SERVICE IF NOT EXISTS core.echo_service
          IN COMPUTE POOL identifier(:pool_name)
          FROM spec='service/echo_spec.yaml';
    
       CREATE OR REPLACE FUNCTION core.my_echo_udf (TEXT VARCHAR)
          RETURNS varchar
          SERVICE=core.echo_service
          ENDPOINT=echoendpoint
          AS '/echo';
    
       GRANT USAGE ON FUNCTION core.my_echo_udf (varchar) TO APPLICATION ROLE app_user;
    
       RETURN 'Service successfully created';
    END;
    $$;
    
    GRANT USAGE ON PROCEDURE app_public.start_app() TO APPLICATION ROLE app_user;
    
    CREATE OR REPLACE PROCEDURE app_public.service_status()
    RETURNS VARCHAR
    LANGUAGE SQL
    EXECUTE AS OWNER
    AS $$
       DECLARE
             service_status VARCHAR;
       BEGIN
             CALL SYSTEM$GET_SERVICE_STATUS('core.echo_service') INTO :service_status;
             RETURN PARSE_JSON(:service_status)[0]['status']::VARCHAR;
       END;
    $$;
    
    GRANT USAGE ON PROCEDURE app_public.service_status() TO APPLICATION ROLE app_user;
    
    Copy

Create a readme for the application package

  1. Modify na-spcs-tutorial/app/README.md to look like the following:

    Welcome to your first app with containers!
    
    Copy

This readme file is visible to consumers that have installed your app.

Create the project definition file

In this section, you will create the project definition file required by the Snowflake CLI.

  1. Modify na-spcs-tutorial/snowflake.yml to look like the following:

    definition_version: 1
    native_app:
       name: hello_snowflake
       artifacts:
          - src: app/*
            dest: ./
          - service/echo_spec.yaml
       package:
          name: na_spcs_tutorial_pkg
          role: tutorial_role
          warehouse: tutorial_warehouse
       application:
          name: na_spcs_tutorial_app
          debug: false
          role: tutorial_role
          warehouse: tutorial_warehouse
    
    Copy

In this section, you defined a local file structure that can be deployed to a Snowflake account as a Snowflake Native App with Snowpark Container Services. In the next section, you will perform this deployment using Snowflake CLI.

Create and test the app

After defining the manifest file, setup script, and service specification for your Snowflake Native App with Snowpark Container Services, you can test the app by deploying it to your account using Snowflake CLI.

Deploy the application

To deploy the application in stage development mode, do the following:

  1. Create the application package and object in your account by running the following command inside the na-spcs-tutorial folder:

    snow app run [-c connection_name]
    
    Copy

    This command displays a confirmation that an application package called na_spcs_tutorial_pkg and an application object called na_spcs_tutorial_app have been created in your account. These names correspond to the names in the snowflake.yml project definition you created in a previous section.

You can use the URL output to the console to view the application. However, you must first ensure it has all necessary privileges to create its container-based service.

You will do this in the next section.

Grant the privileges and test the app

In this section, you will grant the required privileges to the app and test the app by calling the services in the container.

You can run SQL commands using either Snowsight or the Snowflake CLI.

To grant the privileges and test the app, perform the following steps.

Note

To run in Snowflake CLI, try the following syntax:

snow sql -q "<sql>" --role tutorial_role --warehouse tutorial_warehouse
Copy

As in previous steps, you can add -c connection_name to choose a non-default connection.

  1. Grant the CREATE COMPUTE POOL privilege to the app by running the following:

    grant create compute pool on account to application na_spcs_tutorial_app;
    grant bind service endpoint on account to application na_spcs_tutorial_app;
    
    Copy
  2. Run the app_public.start_app procedure we defined in the setup_script.sql file.

    CALL na_spcs_tutorial_app.app_public.start_app();
    
    Copy

    This procedure creates the compute pool, instantiate the service, and creates the service function.

  3. Confirm the function was created by running the following:

    SHOW FUNCTIONS LIKE '%my_echo_udf%' IN APPLICATION na_spcs_tutorial_app;
    
    Copy

    Note

    Consumers cannot see the running service because it runs as part of the Snowflake Native App. For example, running SHOW SERVICES IN APPLICATION na_spcs_tutorial_app; does not return anything.

  4. To verify that the service has been created and healthy, run the following command:

    CALL na_spcs_tutorial_app.app_public.service_status();
    
    Copy

    This command calls the app_public.service_status procedure you defined in the setup script:

    When this procedure returns READY, you proceed to the next step.

  5. To call the service function to send a request to the service and verify the response, run the following command:

    SELECT na_spcs_tutorial_app.core.my_echo_udf('hello');
    
    Copy

    You will see a message from the service we uploaded in an earlier section: Bob said hello.

Teardown the app and objects created in the tutorial

Because the app uses a compute pool, it accrues credits in your account and costs money to run. To stop the app from consuming resources, you must tear down the application object along with any of the account-level objects it created (like our COMPUTE POOL).

  1. To confirm the compute pool is currently running, run the following command:

    snow object list compute-pool -l "na_spcs_tutorial_app_%"
    
    Copy

    You should see a row with an ACTIVE compute pool that was created by the application object.

  2. Run the following Snowflake CLI command to teardown the app:

    snow app teardown --cascade [-c connection_name]
    
    Copy

    Note

    The CASCADE option removes any associated account-level objects owned by the app before it is dropped. This option requires Snowflake CLI 2.4.0 or higher.

  3. Run the snow object list command again to confirm the compute pool has been dropped.

Note

The snow app teardown command drops both the application package and application object; therefore, any stateful data is lost.

Learn more

Congratulations! Not only have you finished this tutorial, but you have worked through the development and publishing life cycle of a Snowflake Native App with Snowpark Container Services.

Along the way, you: