🔖

Wiki.js v2をCompute EngineとCloud SQLでデプロイ

2022/05/16に公開

Wiki.jsは、Node.jsで動くWikiプラットフォームです。この記事では、バージョン2.5.281をGCPのCompute Engineにデプロイします。

https://github.com/requarks/wiki

この記事はV3が出れば不要になります

https://wiki.squarespace.com/news/2021/wiki-js-3-feature-preview-storage

https://wiki.squarespace.com/news/2022/wiki-js-3-feature-preview-storage-delivery-paths

Wiki.jsは記事執筆現在アルファ版のバージョン3で大幅なリファクタリングがされ、ついに画像の外部アップロードができるようになる予定です。

しかし、今回使うV2では、画像のアップロード先は/wiki/data/uploadsディレクトリだけです。

本当はCloud Runで動かして、画像はGCSに置きたいのですが... 仕方なくCompute Engineのインスタンスでコンテナを動かします。V3が出れば、以下の手順は無駄になるでしょう。

以下で使う環境変数について

変数 内容
PROJECT_ID プロジェクトID(番号ではない)
POSTGRES_PASS DBのrootパスワード
DB_PASS DBのwiki用ユーザーのパスワード
REGION GCPのリージョン
CLOUD_SQL_NAME Cloud SQLの名前
  • SQLもVMも同じリージョンに置く前提で進めます。

GCPの準備

$ gcloud config set project $PROJECT_ID
$ gcloud services enable compute.googleapis.com \
  sqladmin.googleapis.com
  • API足りないかもしれないので適宜有効化してください

Cloud SQL

  • PostgreSQLのDBを作成
    • 名前は$CLOUD_SQL_NAME
    • rootパスは$POSTGRES_PASS
  • 俺はCLIで作ったことがないのでコマンドは載せません
  • 項目多いのでGUIでいいでしょう

プロキシをインストール

https://cloud.google.com/sql/docs/mysql/connect-admin-proxy

データベースとユーザーの作成

  • 別に管理画面から接続してもいいんですが、環境変数を使いたいのでローカルから接続
$ gcloud iam service-accounts create cloud-sql-client
$ gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:cloud-sql-client@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/cloudsql.client
$ gcloud iam service-accounts keys create .cloud_sql_key.json \
    --iam-account cloud-sql-client@$PROJECT_ID.iam.gserviceaccount.com
  • このキーはローカルから接続する時だけ使います
$ CLOUD_SQL=$PROJECT_ID:$REGION:$CLOUD_SQL_NAME
$ ~/cloud_sql_proxy -instances=$CLOUD_SQL=tcp:5432 -credential_file=.cloud_sql_key.json
$ URI=postgres://postgres:$POSTGRES_PASS@localhost:5432/postgres
$ psql $URI -c "CREATE USER wiki WITH encrypted password '$DB_PASS';"
$ psql $URI -c "CREATE DATABASE wikidb ENCODING 'UTF8' LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' TEMPLATE 'template0';"
$ psql $URI -c "GRANT ALL PRIVILEGES ON DATABASE wikidb TO wiki;"
  • gcloud CLIでPostgresのロケール周りがうまく設定できないためこうしています
  • gcloudで日本語に適した設定ができるならそっちのほうが早いです...

Compute Engine

先にDockerセットアップ済みのイメージを作る

https://docs.requarks.io/install/ubuntu

  • 適当なVMをUbuntu 20.04で作り
  • GCPの管理画面からSSH接続
  • Docker入れるとこまで進めてください
  • 停止したVMをソースとしてイメージを作ります

スナップショットスケジュール

https://console.cloud.google.com/compute/snapshots

  • アップロードメディアのディスクをバックアップしたいため、スナップショットスケジュールを作る

永続ディスク

https://zenn.dev/eastresident/articles/e4d875a800b4a7

  • ディスクのパフォーマンスはインスタンス依存が大きいらしく、趣味用途なら標準永続ディスクで十分そう
  • 最小の10GBで標準永続ディスクを作成
  • スナップショットスケジュールを選ぶ

インスタンステンプレート

  • さっき作ったイメージを選択
  • 今回は趣味プロジェクトなんで、ブートディスクも標準永続ディスクで
  • ファイアウォールルールは設定不要(LBにつなぐので)
  • API欄で、Cloud SQLのアクセススコープを設定する
    • これはVMのSAとは関係なく必要
  • ネットワーク欄で、ネットワークタグにallow-health-checkを付ける
  • ディスク欄で、アップロードメディアの永続ディスクを追加する
  • 起動スクリプトは以下の通り
sudo docker start cloudsql-proxy wiki wiki-update-companion

インスタンスグループ

https://cloud.google.com/compute/docs/instance-groups/regional-mig-enable-disable-proactive-redistribution

  • さっきのテンプレートと、永続ディスクでステートフルなインスタンスグループを作る
  • ディスクをどちらもステートフルにする
  • 勝手に消されないように以下の設定を変える
    • 自動スケーリングモードはオフ:自動スケーリングしないに設定
    • インスタンスの再配布で、インスタンスの再配布を有効にするチェックボックスをオフに
  • 頻繁に置き換えが発生すると困るため、ヘルスチェックは必要ない
  • ポートマッピングで、http80を設定する (LBで使う)

VMのセットアップ

https://docs.requarks.io/install/ubuntu

GCPの管理画面からSSH接続して、続きの作業をしていきます

VMのファイアウォール

  • 上記記事を参考にファイアウォールを設定してください

フォーマットとマウント

https://cloud.google.com/compute/docs/disks/add-persistent-disk#format_and_mount_linux

  • /wiki/dataを永続ディスクにマウントします
  • 上記のチュートリアルに従い、永続ディスクをフォーマットしてください
$ sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb
$ sudo mkdir -p /mnt/disks/wiki
$ sudo mount -o discard,defaults /dev/sdb /mnt/disks/wiki
$ sudo chmod a+w /mnt/disks/wiki
  • 今回はデバイス名がsdbだったのでこうなります

自動マウント

https://cloud.google.com/compute/docs/disks/add-persistent-disk#configuring_automatic_mounting_on_vm_restart

  • 自動でマウントされるように、上記のチュートリアルに従ってください

VM内で環境変数をセット

$ REGION=(リージョン)
$ PROJECT_ID=$(gcloud config list --format 'value(core.project)')
$ CLOUD_SQL_NAME=(SQL名)
$ CLOUD_SQL=$PROJECT_ID:$REGION:$CLOUD_SQL_NAME
$ DB_PASS=(DBのパスワード)

Cloud SQL Proxyのコンテナ

https://cloud.google.com/sql/docs/postgres/connect-admin-proxy#docker-tcp

  • コンテナ内で使うため、プロキシもコンテナとして動かします
$ sudo docker network create wikinet
$ sudo docker create --name=cloudsql-proxy -h=cloudsql-proxy --network=wikinet \
  -p 127.0.0.1:5432:5432 --restart=unless-stopped gcr.io/cloudsql-docker/gce-proxy:1.30.1 \
  /cloud_sql_proxy -instances=$CLOUD_SQL=tcp:0.0.0.0:5432
  • このコンテナが起動している限り、コンテナ内からはcloudsql-proxy:5432でDBに接続できます

Wiki.jsのコンテナ

https://docs.requarks.io/install/ubuntu

  • ここのコマンドを拝借しますが、DBのホストはプロキシのコンテナのホスト名に変えています
# 永続ディスクをマウントしている前提
$ sudo docker create --name=wiki -e DB_TYPE=postgres -e DB_HOST=cloudsql-proxy -e DB_PORT=5432 -e DB_PASS=$DB_PASS --device=/dev/sdb -v /mnt/disks/wiki/data:/wiki/data -e DB_USER=wiki -e DB_NAME=wikidb -e UPGRADE_COMPANION=1 --restart=unless-stopped -h wiki --network=wikinet -p 80:3000 -p 443:3443 ghcr.io/requarks/wiki:2
$ sudo docker create --name=wiki-update-companion -v /var/run/docker.sock:/var/run/docker.sock:ro --restart=unless-stopped -h wiki-update-companion --network=wikinet ghcr.io/requarks/wiki-update-companion:latest
$ sudo docker start cloudsql-proxy wiki wiki-update-companion
  • これで起動できるはずです

ディレクトリの権限について

https://github.com/linuxserver/docker-wikijs/issues/5

  • バージョン2.5.281現在、セットアップ時に/wiki/data/cacheのmkdirに失敗します
$ sudo docker exec -u root -it wiki bash
# ここは/wiki
$ mkdir data/{cache,uploads}
$ chown -R node:node data
  • 仕方なくコンテナに入って直しました。

ロードバランサ

あとはWiki.js関係ないですが、インスタンスグループをバックエンドサービスとしたロードバランサを設定してください。

ファイアウォールルール

https://cloud.google.com/load-balancing/docs/https/setup-global-ext-https-compute#firewall

  • 上記を参考に、ヘルスチェック用のファイアウォールルールを作成します
  • 多言語対応の設定にすると、パスを変える必要があるので注意してください

IPv4

  • グローバルIPを確保
  • 放置するとかなり請求されるので注意してください

LBのセットアップ

https://cloud.google.com/load-balancing/docs/https/setup-global-ext-https-compute

  • ここを参考にしてください
  • HTTPSへの転送を忘れないこと

Discussion