⚙️

【SvelteKit 入門】アダプター設定・ホスティング・コンテナ運用

2022/10/08に公開

なぜ序盤にデプロイの解説かというと

新規プロジェクトを作成し外部アクセス可能な状態に持っていく

という一連の作業を先にやってしまい、自分のアプリケーションを稼働させる感覚を掴んだ方が全体の理解が深まるというのが私の持論だからです。


シリーズまとめ(随時追加・更新)

【SvelteKit 入門】はじめに
【SvelteKit 入門】作業の前に
【SvelteKit 入門】アダプター設定・ホスティング・コンテナ運用 now reading
【SvelteKit 入門】ルーティング
【SvelteKit 入門】データハンドリング(+page.js)
SvelteKit + microCMS でブログ構築

この記事では実際にファイルを編集していくので、適当なプロジェクトを作って下さい。

## テンプレートはデモアプリ
? Which Svelte app template?
>   SvelteKit demo app
    Skeleton project
    Library skeleton project

## 続く選択項目
何でもかまいませんが、全て `no` にしておくと以降の参考画像とズレがなくなると思います。

1. アダプター設定

公式ドキュメントの該当部分はこちら
https://kit.svelte.dev/docs/adapters
日本語ドキュメントならこっち

デプロイ用の設定「アダプター」

  • SvelteKit は適用されているアダプターに従いビルドを行う
  • デフォルトではadapter-autoがセットされている
  • デプロイ先に合わせて各種adapter-○○が用意されている
  • 各アダプターは npm パッケージとしてインストール
  • 既存パッケージを使わず、自分でカスタマイズする事も可能

ジョイントパーツを付け換えるイメージ。
最初に付いてるパーツadapter-autoからの換装を解説します。

アダプターの選択肢

公式のリポジトリに、用意されているアダプターが見やすく一覧になってる部分があります。
GitHub 公式リポジトリ README.md
有名どころのホスティングサービス向けは用意されていますね。
※サービス名ではないアダプターについては後ほど補足

ファイル編集

編集するファイルは2つあります。

① package.json


package.jsondevDependencies

ここに使用するadapter-○○がないといけません。adapter-autoは既に入ってますね。
このadapter-autoを書き換える or 下の行に追記 どちらかをしてください。


Vercel用アダプターに書き換えた例

ファイルを編集して保存したら、再度

npm install

を実行して下さい。

② svelte.config.js

ここもデフォルトはadapter-autoになっていると思うので、使用するものに合わせて書き換えます。ここは追記ではなく書き換えです。(残すならコメントアウト)

ちなみに下の adapter: adapter() 部分はこのままでokです。
詳細な設定をする場合はオプションをJSON形式で入れることになります。

アダプター設定まとめ

以上がアダプター設定の流れです。要するに

  • 使うadapter-○○のパッケージがインストール済で
  • svelte.config.jsでそれをimport & config.kit.adapter に設定

これがクリアされていればジョイントパーツの付け換えは完了です。
ホスティングサービスに慣れてる方は、もうデプロイしてみて下さい。

【補足】adapter-autoはダメなの?

実はたいていadapter-autoのままでいけます

しかしデプロイ先でエラーが出た時の原因切り分けや、アプリケーションの構成に合わせてアダプターを変更する必要が出てきた場合等、理解しておけば何かと便利なので早い段階で触っておいて欲しかった という私個人の押し付けが発動したせいです。すみません。

ホスティングサービス向け 以外の アダプターについて少し解説

atapter-auto 自動判別。大手ホスティングサービスなら無設定でいける可能性が高い
adapter-static 静的ファイル群で出力。
nginxGitHub Pagesといった(非Nodeの)WEBサーバーでも運用可能
サーバー側でjsが動くようなレンダリングをしないという事であって、ブラウザ駆動のjsは動く。SPAも可。
adapter-node Node環境向け。
コンテナでNode.jsメージに入れて稼働、PM2でクラスター化して稼働、などなど
自分でカスタマイズ adapterをimportするのではなく、JSONで設定を記述

アダプターの使い分けにおいては 実装するレンダリングの種類 も少し関わってきますので、SvelteKit の理解が深まったら色々検証してみてください。

2. ホスティングサービスにデプロイ

SvelteKit を動かす環境は色々と考えられますが、まずはシンプルなホスティングサービスを利用するのが良いかと思います。GitHub と連携さえすれば、push するだけでビルド&デプロイを回してくれる環境は非常に快適です。

Vercel, Cloudflare Pages, Netlify の3サービスで設定時の要所のみまとめました。

準備

  • プロジェクトをGitHub管理
  • Vercel / Cloudflare / Netlify いずれかのアカウント
  • ↑ サービスに向けてGitHubの権限許可

この部分は解説しませんので、自力解決でお願いします。

では各サービスでの作業を簡単に。

Vercel

FRAMEWORK PRESETSvelteKit を選択する だけ
(しかも多分最初から自動で選択されてる)

Cloudflare Pages

フレームワーク プリセットSvelteKit を選択。
続いて 環境変数(アドバンスド) を展開します。

+変数を追加する をクリックし、NODE_VERSION = 16 に設定


ちなみに17でもいけます。18は未対応(2022年10月時点)

Netlify

プリセットの選択すら無い。値はデフォルトから変更不要。
Base direcroty はブランクのままでok。


Build command は自動で判別したのだろうか

比較

サービスごとでビルド環境等に若干違いはありますが、設定し直さなくてもadapter-autoが柔軟に調整してくれているようです。当然専用のアダプターに変えても正常に稼働します。

Vercel Cloudflare Pages Netlify
出力ディレクトリ
(初期値)
/public /.svelte-kit/cloudflare /build
Nodeバージョン
(初期値)
16
※設定で12,14,16が選択可
12
※環境変数で17まで指定可
16
※環境変数で18まで指定可
ビルド速度 ▲   →   ◎
(   初回   → 2回目〜)
アクセス速度

VercelNetlifyはデフォルトのNodeバージョンが16以上なのでそのままいけますが、Cloudflare Pagesはデフォルトが12なので、環境変数で16以上の値にすることで対応できます。

3. コンテナ運用

docker-composeは無し、Dockerfileからのイメージビルド→立ち上げ の流れで行きます。

準備

コンテナ稼働で必要なSvelteKit側の設定は
アダプターを adapter-node に変更する
これだけです。

起動条件の確認

各段階で必要なファイル・ディレクトリは以下のようになってます

実行コマンド    必要            出力される(影響を受ける)  
npm install package.json .svelte-kit/
node_modules/
package-lock.json
npm ci package.json
package-lock.json
.svelte-kit/
node_modules/
npm run build node_modules/
src/
static/
package.json
svelte.config.js
vite.config.js
.svelte-kit/
build/
SvelteKit 起動 build/
node_modules/
package.json
----

これらを踏まえ、マルチステージビルドにすることでイメージサイズを何割か小さくできます。

イメージ作成

Dockerfile
#### 前半はビルド用ステージ
FROM node:18-slim AS STAGE_NAME_OF_BUILD
WORKDIR    /DIR_FOR_BUILD
COPY       . .
RUN        npm install && npm run build

#### 後半は起動用ステージ
FROM node:18-slim
WORKDIR    /DIR_FOR_RUN
COPY       --from=STAGE_NAME_OF_BUILD /DIR_FOR_BUILD/package.json .
COPY       --from=STAGE_NAME_OF_BUILD /DIR_FOR_BUILD/build ./build
RUN        npm install --omit=dev
                       # ↑ --produnction よりこちらが推奨になった模様
ENV        PORT PORT_NUMBER
                # ↑ ポートを変更したい場合は指定。3000のままで良いなら不要
CMD        ["node","build"]

大文字スネークケースの部分は好きなものに変更してください。

全体

Dockerファイルが複雑になりすぎない、程々のパターンにしました。これでも十分イメージサイズは削減できます。
イメージは私がslim派なだけで、alpineでも可。Googleのdistrolessを使う場合はステージングがもっと複雑になるので今回は見送りました。
マルチステージの場合、最後のステージに持ってくるファイルがイメージサイズに直結します。.dockerignoreでビルドステージへのコピーを減らしてもイメージサイズには影響ありません。

パッケージのインストール

npm installnpm ciの使い分けについては長くなるのでここでは割愛します。
依存関係がシビアな場合はnpm ciに変えてください。

NODE_ENV

ENV NODE_ENV production等の記述は、プロジェクト内で環境変数を扱う段階になったら追記してください。少なくとも「環境変数?なにそれ」という段階では記述無しで大丈夫です。

EXPOSE

EXPOSEでポート番号を入れている資料もありますが不要です。
(起動時の-p 外部ポート:内部ポートオプションは必要です)

コンテナ起動

Cloud Run等のCaaS利用だったり、昨今のコンテナ環境は様々だと思いますが…
マシン上で直接podmanを使う というなかなかニッチなケースの例を載せておきます。

# SvelteKit のディレクトリに上記 Dockerfile を配置
# そのディレクトリで以下のコマンド
# --squash-all はお好みで
podman build -t イメージ名:タグ --squash-all .

# コンテナ起動
podman run -d --init -p 受け付けたいポート:3000 イメージ名

ちなみにpodmanの場合、DockerfileではなくContainerfileというファイル名でもいけます。

運用時の構成

接続のSSL化やテスト環境との振り分けなどを考えると、リバースプロキシを挟むのが現実的です。

外からのhttps接続をnginxで受け、内部はhttp接続でSvelteKitのコンテナに回す という構成が最もシンプルかと思います。私はpodmanユーザーですが、nginx-SvelteKitの通信は同一podで接続するパターン、ネットワークを作成しIPを振って接続するパターン、どちらも問題ありませんでした。

ここで格好良くアーキテクチャ図とともにサンプルコードを記載できれば良いのですが、オレオレ設定も非常に多くお見せするには散らかり過ぎているので見送らせていただきます。

【補足】"デプロイ"という表現

この記事ではデプロイを結構広い意味で使いましたがご了承ください。
例えば Vercel を利用する場合、

  1. GitHub と連携 & 設定
  2. push
  3. Vercel が自動でビルド & デプロイ

というフローが流れていきます。
つまり厳密に言えば、デプロイは Vercel 内部で行われている工程の一つなわけですが・・・
この 外部アクセスが可能な状態まで持っていくこと をデプロイと呼びました。

まとめ

デモアプリはサーバー上で動いてますか?
これで今後 SvelteKit で何か作ってみた際、ローカルに限らず動作検証ができますね。

本記事の内容(特にコンテナのDockerfileまわり)について、何かお気づきの点があれば気軽にコメントください。

Discussion