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
3.0.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:
To create the
tutorial_role
role, run the following command:CREATE ROLE tutorial_role;
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>;
Where:
user_name
Specifies the name of the user who will perform the tutorial.
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;
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
Create a warehouse and image repository¶
To create the required objects, perform the following either through Snowsight or Snowflake CLI.
To set the current context in Snowsight to use the
tutorial_role
role, run the following command:USE ROLE tutorial_role;
If you are using Snowflake CLI, you can use
--role tutorial_role
instead.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;
A warehouse is required by the Snowflake Native App to run SQL commands and stored procedures.
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;
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.
On your local file system, run the following command to create a folder named
na-spcs-tutorial
:snow init --template app_basic na-spcs-tutorial
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 init --help
to see other templates for setting up a Snowflake Native App development environment.Create a folder called
service
inside thena-spcs-tutorial
folder. This folder contains the source code for the container-based service we are about to build and publish to Snowflake.To obtain the Docker files required for the tutorial, download the zip file to your local file system.
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
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:
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 .
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.
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
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.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>
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
andmy_echo_service_image:tutorial
:docker tag my_echo_service_image:tutorial $REPO_URL/my_echo_service_image:tutorial
To authenticate with the Snowflake registry, run the following Snowflake CLI command:
snow spcs image-registry login [-c connection_name]
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.To upload the Docker image to the image repository, run the following
docker push
command:docker push $REPO_URL/<image_name>
Using the same value as
<image_name>
from previous steps, this command is:docker push $REPO_URL/my_echo_service_image:tutorial
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
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:
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"
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:
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;
Create a readme for the application package¶
Modify
na-spcs-tutorial/app/README.md
to look like the following:Welcome to your first app with containers!
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.
Modify
na-spcs-tutorial/snowflake.yml
to look like the following:definition_version: 2 entities: na_spcs_tutorial_pkg: type: application package manifest: app/manifest.yml artifacts: - src: app/* dest: ./ - service/echo_spec.yaml meta: role: tutorial_role warehouse: tutorial_warehouse na_spcs_tutorial_app: type: application from: target: na_spcs_tutorial_pkg debug: false meta: role: tutorial_role warehouse: tutorial_warehouse
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:
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]
This command displays a confirmation that an application package called
na_spcs_tutorial_pkg
and an application object calledna_spcs_tutorial_app
have been created in your account. These names correspond to the names in thesnowflake.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_warehouseAs in previous steps, you can add
-c connection_name
to choose a non-default connection.
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;
Run the
app_public.start_app
procedure we defined in thesetup_script.sql
file.CALL na_spcs_tutorial_app.app_public.start_app();
This procedure creates the compute pool, instantiate the service, and creates the service function.
Confirm the function was created by running the following:
SHOW FUNCTIONS LIKE '%my_echo_udf%' IN APPLICATION na_spcs_tutorial_app;
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.To verify that the service has been created and healthy, run the following command:
CALL na_spcs_tutorial_app.app_public.service_status();
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.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');
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
).
To confirm the compute pool is currently running, run the following command:
snow object list compute-pool -l "na_spcs_tutorial_app_%"
You should see a row with an
ACTIVE
compute pool that was created by the application object.Run the following Snowflake CLI command to teardown the app:
snow app teardown --cascade [-c connection_name]
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.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:
Used Snowsight and Snowflake CLI to build an application using the Snowflake Native App Framework.
See Configuring Snowflake CLI and connecting to Snowflake for more information on how to configure the connections used by Snowflake CLI.
For more information about Snowsight, refer to Getting started with worksheets and Work with worksheets in Snowsight.
For more information about Native Apps in Snowflake CLI, refer to Using Snowflake Native App in Snowflake CLI.
Created the manifest and setup script that are required by all applications.
Refer to Create the manifest file for an application package and Create a setup script for details.
Created an application package that works as a container for the application logic and data content of your application.
Refer to Create an application package for details.
Used Docker CLI and Snowflake CLI to build and upload a container to Snowflake.
Used Snowpark Container Services to create a
COMPUTE POOL
and instantiate the container inside of a Snowflake Native App.