Open8

内部ツール向けデプロイツール「Clace」を試す

kun432kun432

https://clace.io/

Clace

概要

ClaceはApache-2.0ライセンスのプロジェクトで、社内ツール用のウェブアプリ開発とデプロイメント・プラットフォームを構築している。Claceは、あらゆる言語/フレームワークの複数のウェブアプリを、1台のマシンで簡単かつ安全にホスティングできる。Claceはクロスプラットフォーム(Linux/Windows/OSX)で、ウェブアプリを管理するためのGitOpsワークフローを提供する。

Claceは、リバースプロキシ、ハイパーメディアベースのマイクロフレームワーク、コンテナオーケストレータ(DockerまたはPodmanを使用)の機能を単一の軽量バイナリに統合している。Claceサーバーを起動し、DockerまたはPodmanが動作していることを確認した後、新しいアプリをGitHubのソース・レポから1つのコマンドでインストールできる。Claceはイメージをビルドし、最初のAPIコールでコンテナを起動する。

Claceは、開発マシン上で任意のコンテナ化されたウェブアプリを開発し、共有サーバー上にアプリをデプロイするために使用できる。アプリはgitリポジトリから直接デプロイされ、ビルドステップは必要ない。ClaceはStreamlitアプリのデプロイに使用でき、チーム全体のアクセス制御のためにOAuth認証を追加できる。

このリポジトリはClaceサーバとクライアントのソースコードをホストしている。ドキュメントサイトclace.ioのソースはdocs repoにある。アプリをビルドするためのテンプレートであるアプリ仕様は、appspecsレポで定義されている。

kun432kun432

特徴

Claceは以下の用途に使用できる:

  • コンテナ化されたアプリケーションをデプロイし、Claceがコンテナのライフサイクルを構築・管理する。
  • Starlarkを使ってハイパーメディアベースのアプリケーションを構築する(コンテナは不要)
  • バックエンドAPIをコンテナで実装し、ハイパーメディアベースのUIをClaceで実装するハイブリッドアプローチ

Claceはすべてのアプリケーションで以下をサポートする:

  • 複数のアプリのアトミックアップデート。
  • アプリのアップデートのステージング・モード。コードやコンフィグの変更が本番環境で動作するかどうかを、本番環境で動作させる前に検証する。
  • コード変更を試すためのプレビューアプリ作成サポート。
  • githubとの統合をサポートし、アプリをgithubのコードから直接デプロイできる。
  • OAuthとSSOベースの認証
  • アプリレベルでドメインベースとパスベースのルーティングをサポート。

コンテナ化されたアプリに対して、Claceは以下をサポートする:

  • devおよびprodモードでのイメージビルドの管理
  • コンテナのパラメータを渡す
  • サポートされているフレームワーク(Flask、Streamlit、Containerfileを持つレポ)については、レポのコードを変更することなく、仕様書からアプリをビルドできる。

ハイパーメディアベースのアプリをビルドするために、Claceは以下をサポートしている:

  • 自動エラー処理のサポート
  • esbuildを使用したECMAScriptモジュールの自動作成。
  • TailwindCSSとDaisyUIウォッチャー統合のサポート。
  • certmagicに基づくSSL証明書の自動作成。
  • バックエンドのアプリコードは、allowlistベースのパーミッションを持つセキュリティサンドボックスで実行される。
  • ビルドステップがなく、開発成果物は本番環境ですぐに使用できる。
  • SQLiteを使用したアプリケーション・データの永続化のサポート
  • SQLiteデータベースによってバックアップされたコンテンツ・ハッシュ・ベースのファイル名を持つ仮想ファイルシステムにより、積極的な静的コンテンツ・キャッシュが可能になる。
  • 静的アーティファクトのBrotli圧縮、パフォーマンスのためのHTTPアーリーヒントのサポート。
kun432kun432

Quick Startを進めていく。今回はローカルのLAN内にいるUbuntu 22.04サーバで。

https://clace.io/docs/quickstart/

インストールスクリプトが用意されているのでそれを実行。インストールスクリプト使うタイプは環境を隔離できなくて何やってるかがぱっとわからないので個人的には好みではないのだけど、中身を確認した感じ

  • tar.gz落としてきて展開
  • ファイル・ディレクトリ配置しつつ初期設定ファイルを生成

ぐらいっぽいので、素直に実行した。

$ curl -L https://clace.io/install.sh | sh
######################################################################## 100.0%

clace was installed successfully to /home/kun432/clhome/bin/clace

Generated password is: XXXXXXXXXXXXXXXX


Password config has been setup, save the above password for app access with admin account
Manually add the following to your $HOME/.bash_profile (or similar). Also run it now for this session:

  source "/home/kun432/clhome/bin/clace.env"

See https://clace.io/docs/quickstart for quick start guide.

諸々は$HOME/clhome以下にインストールされる模様。あとadminアカウント用のパスワードも自動生成されるが、どうやらアプリデプロイ後のアクセスに必要になる様子。一旦控えておく。

$ tree /home/kun432/clhome
/home/kun432/clhome
├── bin
│   ├── clace
│   └── clace.env
├── clace.toml
└── tmp
    └── clace-v0.6.5-linux-amd64
        ├── LICENSE
        └── README.md

3 directories, 5 files

画面の指示通り、環境設定用の1行を.bash_profileなり.bashrcなりに追加する。自分は.bashrcに追加。

~/.bashrc
source "/home/kun432/clhome/bin/clace.env"

.bashrcを再読み込み

$ exec $SHELL -l

PATHが通った。

$ which clace
/home/kun432/clhome/bin/clace

ではclaceのサーバを起動する。

$ clace server start &
[1] 1503168
Server listening on http://127.0.0.1:25222
Server listening on https://0.0.0.0:25223

ローカルからアクセスする場合は、25222番ポート、リモートからアクセスする場合は25223番ポートにアクセスすれば良さそう。

ということでリモートからアクセスしてみた(証明書の警告が表示されるのはスルー)

今のところアプリを何もデプロイしていないので何も表示されない様子。管理画面とかも特になくてCLIがメインになるのかな?

kun432kun432

Usage一応見ておく。

$ clace --help
NAME:
   clace - Clace client and server https://clace.io/

USAGE:
   clace [global options] command [command options] [arguments...]

COMMANDS:
   server    Manage the Clace server
   app       Manage Clace apps
   preview   Manage Clace preview apps
   account   Manage Clace accounts
   param     Manage app parameter values
   version   Manage app versions
   password  Generate a password bcrypt config entry
   help, h   Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --config-file value, -c value  TOML configuration file [$CL_CONFIG_FILE]
   --version, -v                  Print version info (default: false)
   --help, -h                     show help

以下のサブコマンドがある様子。

  • server
  • app
  • preview
  • account
  • param
  • version
  • password

clace appがアプリ関連のコマンドに思える。こちらもUsageを見てみる。

$ clace app --help
NAME:
   clace app - Manage Clace apps

USAGE:
   clace app command [command options] [arguments...]

COMMANDS:
   create           Create a new app
   list             List apps
   delete           Delete an app
   approve          Approve app permissions
   reload           Reload the app source code
   promote          Promote the app from staging to production
   update-settings  Update Clace apps settings. Settings changes are NOT staged, they apply immediately to matched stage, prod and preview apps.
   update-metadata  Update Clace app metadata. Metadata updates are staged and have to be promoted to prod. Use "clace param" to update app parameter metadata.
   help, h          Shows a list of commands or help for one command

OPTIONS:
   --help, -h  show help

サブコマンドごとにサブコマンドがある模様。crace app createでアプリがデプロイできるっぽい。

kun432kun432

アプリのデプロイ

ではClaceを使ってアプリをデプロイする。Quick Startでは以下のレポジトリで公開されているいるデモアプリのうち、

  • disk_uasge
  • bookmarks

をデプロイする様子。

https://github.com/claceio/apps

とりあえずdisk_usageアプリからやってみる。githubレポジトリから直接デプロイできるっぽい。

$ clace app create --approve github.com/claceio/apps/system/disk_usage /disk_usage
App audit results /disk_usage - app_prd_2i0elsayewvbxlcsoxpaqigui0b
App audit results /disk_usage_cl_stage - app_stg_2i0elsayewvbxlcsoxpaqigui0b
  Plugins :
    fs.in
  Permissions:
    fs.in.abs []
    fs.in.list []
    fs.in.find []
App created. Permissions have been approved

 HTTP Url: http://localhost:25222/disk_usage
HTTPS Url: https://localhost:25223/disk_usage

アプリがデプロイされた様子。ブラウザでhttps://X.X.X.X:25223/disk_usageにアクセス(ホスト名は適宜変更)してみると、BASIC認証のダイアログが開く。ユーザ名はadmin、パスワードはclaceサーバ起動時に表示されたパスワードを入力する。

claceのインストールディレクトリ内のディスク使用状況を表示するサンプルっぽい。

もう一つのbookmarksアプリもデプロイしてみる。

$ clace app create --approve github.com/claceio/apps/utils/bookmarks /book
App audit results /book - app_prd_2i0gfm0za1peptgguhemklnziuy
App audit results /book_cl_stage - app_stg_2i0gfm0za1peptgguhemklnziuy
  Plugins :
    store.in
  Permissions:
    store.in.select []
    store.in.insert []
    store.in.update []
    store.in.select_one []
    store.in.begin []
    store.in.commit []
    store.in.delete_by_id []
App created. Permissions have been approved

 HTTP Url: http://localhost:25222/book
HTTPS Url: https://localhost:25223/book

同様にブラウザでアクセスしてみるとこんな感じ。

なお、clace app create時に--auth noneをつけると認証が無効化される様子。

kun432kun432

アプリのコンテナ化

さきほどデプロイしたデモアプリは、ビルドツールBazekの設定言語であるStarlarkのgo実装、Starlark-goで書かれている。どうやらStarlarkで書かれている場合はコンテナ等が不要・Claceサーバで直接動作するらしい。

逆にそれ以外の言語で書かれたアプリの場合はコンテナが使用される。デフォルトではpodmanが使用され、見つからない場合はdockerになる。

アプリのコンテナ化には2つの方法がある

  1. 必要なファイルをレポジトリに入れておく。
    • app.star
      • アプリの設定。多分Starlarkで書く。
    • Containerfile / Dockerfile
      • コンテナの設定。
  2. (AppSpec)(https://clace.io/docs/app/overview/#building-apps-from-spec)を指定する。
    • アプリごとのデプロイ用テンプレートのようなもの?
    • 作成したアプリのコードの変更は一切不要、コンテナ設定ファイルも不要
    • サポートしているAppSpecは https://github.com/claceio/appspecs にある
      • container
      • image
      • proxy
      • python-flask
      • python-streamlit-poetry
      • python-streamlit

ここでは2のパターンを見てみる。streamlitが公開しているデモアプリのレポジトリを使ってデプロイしてみる。

https://github.com/streamlit/streamlit-example

$ clace app create \
    --spec python-streamlit \
    --branch master \
    --approve \
   github.com/streamlit/streamlit-example /streamlit
App audit results /streamlit - app_prd_2i0w9ijw5ywcjlzdras0ormgszx
App audit results /streamlit_cl_stage - app_stg_2i0w9ijw5ywcjlzdras0ormgszx
  Plugins :
    proxy.in
    container.in
  Permissions:
    proxy.in.config [<CONTAINER_URL>]
    container.in.config [auto]
App created. Permissions have been approved

 HTTP Url: http://localhost:25222/streamlit
HTTPS Url: https://localhost:25223/streamlit

URLにアクセスしてみる。表示されるまでにちょっと時間がかかる。

裏では以下が行われている。

  • 上記のgithubレポジトリがクローンされる
  • クローンしたレポジトリ内に、Claceで起動させるために必要なファイルをAppSpec python-streamlitからコピーする
  • アプリのソースやメタデータをClaseサーバのメタデータデータベース(SQlite)に読み込む
  • アプリAPIへの初回アクセス時に、Claceサーバは以下を実行する
    • AppSpecに定義されているContainerfileを使ってコンテナイメージを作成
    • イメージからコンテナを起動し、アプリAPIへのプロキシをセットアップ

docker psを見てみるとたしかに起動していた。

$ docker ps
CONTAINER ID  IMAGE                    COMMAND                 CREATED        STATUS        PORTS                      NAMES
d4fe081913ac  cli-app_prd_XXXXXXXX...  "bash -x /streamlit_…"  9 minutes ago  Up 9 minutes  127.0.0.1:32768->8501/tcp  cli-app_prd_XXXXXXXX...
(snip)

アプリへパラメータを渡す場合にはapp paramsを使うか、または、アプリデプロイ時に直接指定(ex: app create --param port=9000)したり、アプリ起動後に変更(ex: param update port 9000 /myapp)したりできる様子。

ソースのレポジトリにContainerfileもしくはDockerfileがあれば、どの言語やフレームワークでも使用可能な汎用のcontainer specが使用される。コンテナファイルにEXPOSEが設定されていればポートは指定しなくても良い。

ちなみに、AppSpecの中身がどうなっているかを見てみると、どうやらStarlarkの設定ファイル(app.starparams.star)はあらかじめ用意されていて、これは必須っぽい。

このあたりは隠蔽されていてあまり来にしなくていいのかもしれないけど、なんとなくStarlarkの記法とかに慣れておいたほうが良さそうに思える。以下はcontainerspecのapp.starの中身。一応「Pythonの方言」という扱いらしいので、なんとなく読める感。

https://github.com/claceio/appspecs/blob/main/container/app.star

kun432kun432

アプリの管理

Claceサーバーには複数のアプリケーションをインストールでき、各アプリケーションは固有のパスを持ち、個別に管理が可能。
アプリのパスはdomain_name:url_pathで構成され、アプリ作成時にdomain_nameが指定されない場合はデフォルトドメインで作成される。
特定のドメインに一致するものが見つからない場合、デフォルトドメインが検索される。
ルーティングの詳細はapp routingを参照

ローカル環境では、URLベースのルーティングを使用するか、*.localhostドメインをドメインベースのパスに使用することができる。
本番環境では、ワイルドカードDNSがセットアップされていれば、アプリごとに新しいDNSエントリを作成することなく、ドメインベースのルーティングを使用できる。アプリは、1つのClaceサーバー上の複数の異なるドメインでホストすることができる。

kun432kun432

アプリのインストール

アプリのインストールは

clace app create --appprove <source_url> <[domain:]app_path

で行う。例えばdisk_usageのデモだとこうなる。

$ clace app create --approve github.com/claceio/apps/system/disk_usage /disk_usage
  • github.com/claceio/appsレポジトリのmainブランチから system/disk_usageのソースを取得してインストール
  • デフォルトドメインの /disk_usageのパスで動作するように設定

アプリのコードがローカルにある場合はsource_urlでパスを指定すれば良い。

clace app create --approve ./diskapp /disk_usage_local

ローカルにコードがある場合は--devオプションを付けるとdevモードになり、コードを変更するとリロード等を行わなくても自動で反映される。
devモード以外=prodモードの場合はアプリのリロード(app reload)が必要になる。リロードは以下。

clare app reload --approve --promote "/disk_usage"

githubレポジトリからインストールしたアプリでapp reloadを行うと、アプリ作成時に指定したブランチ(デフォルトはmain)から最新の変更が取得されて反映される。

devモード以外の場合、コードはSQLiteメタデータデータベースに読み込まれてClaceサーバで管理される。