CCCMKホールディングス TECH LABの Tech Blog

TECH LABのエンジニアが技術情報を発信しています

ブログタイトル

Dockerで作ったコンテナアプリをSnowflakeで動かしてみる!~Snowpark Container Services~

こんにちは、CCCMKホールディングスAIエンジニアの三浦です。最近オフィスが変わり、電車に乗っている時間が長くなりました。「読まないと」と思ってため込んでいた論文や記事を集中して読んでいく時間として活用しています。

最近Snowflakeでコンテナアプリを動かすことが出来る、という話を知り、どんな感じなのか試してみたいと思いました。利用するのは"Snowpark Container Services"というSnowflakeのフルマネージドコンテナサービスで、今回は開発環境でDockerで作っていたコンテナアプリをこの機能を使ってSnowflakeで動かしてみる、という話をご紹介していきます。

Snowpark Container Servicesとは

Snowpark Container Servicesはフルマネージドなコンテナサービスで、イメージの管理から複数コンテナを組み合わせたサービスの稼働まで、Snowflake上で完遂することが出来る面白いサービスです。ドキュメントはこちらです。

docs.snowflake.com

Snowflake上でコンテナアプリを動かすまでの流れは、ざっと次のようになります。

  • ビルドしたイメージを登録するImage RepositoryをSchema配下に作成する
  • アプリを動かすためのCompute Poolを作成する
  • 開発環境でビルドしたイメージをImage Repositoryにpushする
  • サービスの定義ファイルをYAML形式で書く
  • サービスを作成し、アプリを動かす

今回はこの流れに従って手順をまとめていきます。

初期設定

検証用の環境を作成しました。手順はこちらのSnowpark Container Servicesの共通セットアップの内容に従っています。

docs.snowflake.com

SQLクエリを実行して進めていきます。まず検証用のRoleを作成します。

CREATE ROLE test_role;

検証用のDatabaseを作成し、test_roleに権限を付与します。

CREATE DATABASE IF NOT EXISTS tutorial_db;
GRANT OWNERSHIP ON DATABASE tutorial_db TO ROLE test_role COPY CURRENT GRANTS;

検証用のWarehouseの作成と利用権限をRoleに付与。

CREATE OR REPLACE WAREHOUSE tutorial_warehouse WITH
  WAREHOUSE_SIZE='X-SMALL';
GRANT USAGE ON WAREHOUSE tutorial_warehouse TO ROLE test_role;

アプリを動かすためのCompute Poolの作成と権限をRoleに付与。

CREATE COMPUTE POOL tutorial_compute_pool
  MIN_NODES = 1
  MAX_NODES = 1
  INSTANCE_FAMILY = CPU_X64_XS;
GRANT USAGE, MONITOR ON COMPUTE POOL tutorial_compute_pool TO ROLE test_role;

アプリのEndpointへのアクセス権限のRoleへの付与と、RoleのUserへの付与を行います。

GRANT BIND SERVICE ENDPOINT ON ACCOUNT TO ROLE test_role;
GRANT ROLE test_role TO USER test_user

あとはDatabaseに検証用のSchemaを作り、Image Repositoryとサービス定義ファイル置き場用のStageを作成しました。

USE ROLE test_role;
USE DATABASE tutorial_db;
USE WAREHOUSE tutorial_warehouse;

CREATE SCHEMA IF NOT EXISTS data_schema;
CREATE IMAGE REPOSITORY IF NOT EXISTS tutorial_repository;
CREATE STAGE IF NOT EXISTS tutorial_stage
  DIRECTORY = ( ENABLE = true );

開発環境からイメージをpushする

今度はアプリの開発環境で作業を行います。イメージをビルドしてImage Registry配下のRepositoryにpushするのですが、Snowflakeに接続するために最初にSnowflake CLIをインストールしました。

実行したコマンドはこちらです。

wget https://sfc-repo.snowflakecomputing.com/snowflake-cli/linux_x86_64/3.5.0/snowflake-cli-3.5.0.x86_64.deb
sudo dpkg -i snowflake-cli-3.5.0.x86_64.deb

最初CLIのバージョンが3.8.3のものをインストールしたのですが、コマンドを実行するとIllegal instruction (core dumped)というメッセージが表示されて起動することが出来ませんでした。おそらくこちらと同様の現象で、このイシューには3.5だと上手くいった、と書いてあったため今回3.5.0をインストールしています。

github.com

Snowflakeへの接続にはキーペア認証を使用しました。秘密鍵や公開鍵の登録手順はこちらを参考にしています。

docs.snowflake.com

接続情報はtomlファイルに記入しました。以下のような内容です。

default_connection_name = "myconnection"

[connections]
[connections.myconnection]
account = "ACCOUNT_NAME"
user = "test_user"
authenticator = "SNOWFLAKE_JWT"
private_key_file = "./rsa_key.p8"

[cli.logs]
save_logs = true
level = "info"
path = "/home/xx/.snowflake/logs"

あらかじめ作成済みのコンテナアプリのディレクトリ内でイメージをビルドします。 ちなみに今回のアプリのDockerfileは以下のようにしました。streamlitが動くようになっています。

FROM python:3.12.7-slim
WORKDIR /app
COPY ./requirements.txt .
RUN pip install -r requirements.txt
COPY ./src ./src
WORKDIR ./src
EXPOSE 8501
CMD ["streamlit","run","app.py"]

buildしてタグ付けをします。RepositoryのURLは以下に従って設定しました。

docs.snowflake.com

docker build -t account.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/test-app

Snowflake CLIでRegistryにログインします。

snow --config-file=connection.toml spcs image-registry login

イメージをpushします。

docker push account.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/test-app

サービス定義ファイルの作成

次にサービスを定義するYAMLファイルを作成します。"docker-compose.yml"の形式に似ています。複数のコンテナを指定することが出来ますが、今回はコンテナ1つの構成です。containersの箇所で起動するコンテナの情報を記入しています。imageには先ほどpushしたイメージのパスを指定しています。envには環境変数を設定できます。また、readinessProbeを上手く使うとアプリ起動時のヘルスチェックの処理を指定出来るようです。(今回は特に処理を作っていません。)

endpointsがこのサービスのEndpointを示しています。public: trueにすることで同一アカウント内の権限があるユーザーがアクセスできるようになります。

spec:
  containers:
    - name: app
      image: /tutorial_db/data_schema/tutorial_repository/test-app
      env:
        SERVER_PORT: 8501
        ...
      readinessProbe:
          port: 8501
          path: /
  endpoints:
    - name: app
      port: 8501
      public: true

この内容をspec.yamlとして保存し、Stage上に格納しました。

サービスの作成

あとは以下のSQLクエリを実行してサービスを作成しました。

USE ROLE test_role;
USE DATABASE TUTORIAL_DB;
USE SCHEMA DATA_SCHEMA;

CREATE SERVICE test_app
 IN COMPUTE POOL tutorial_compute_pool
 FROM @TUTORIAL_STAGE
 SPECIFICATION_FILE='spec.yaml'
 MIN_INSTANCES = 1
 MAX_INSTANCES = 1;

サービスの作成が完了した後は、以下のクエリでエンドポイントのURLを確認出来るようになります。

SHOW ENDPOINTS IN SERVICE test_app;

実行結果に含まれる"ingress_url"にアクセスすると、アカウントへのログイン画面が表示され、ログインが完了するとsnowflakeのアプリが表示されます!

まとめ

今回はSnowpark Container Servicesを使ってSnowflakeの中でコンテナアプリを動かす、といったことを試してみました。手順が多いのでハードルが高く感じていたのですが、いざやってみるとそれほど詰まるところもなく、スムーズに進めることが出来ました。またアプリへの認証もSnowflakeの機能を利用できるのもいいな、と思います。

この後はSnowflakeに格納されたTableにコンテナアプリからアクセスさせたり、作ったアプリをパッケージ化する方法なども調べていきたいと思います。