Open5

PleasanterをTiDBで動かす

bohnenbohnen

プリザンターをTiDBで動かすまでのメモ

MacOS上で、docker composeを使ってPleasanter + TiDB Playgroundで(なんとか)動かせたのでメモしておく。

bohnenbohnen

プリザンターのセットアップ

https://pleasanter.org/ja/manual/setup-by-docker-image-and-mysql の手順を簡略化して利用する。

ディレクトリ構成.txt
.
|-- compose.yaml
|-- .env
|
+-- app_data_parameters
|   +-- RDS.json
|
+-- docker-entrypoint-initdb.d
|   +-- pleasanter.sql
|
+-- CodeDefiner
|   +-- Dockerfile
|
+---Pleasanter
    +-- Dockerfile

それぞれのファイルは次のようなもの

compose.yaml
services:
  pleasanter:
    build:
      context: .
      dockerfile: ./Pleasanter/Dockerfile
      args:
        - VERSION=${PLEASANTER_VER}
    container_name: pleasanter_${PLEASANTER_VER}
    ports:
      - '50001:8080'
    environment:
      Implem.Pleasanter_Rds_MySQL_SaConnectionString: ${Implem_Pleasanter_Rds_MySQL_SaConnectionString}
      Implem.Pleasanter_Rds_MySQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_MySQL_OwnerConnectionString}
      Implem.Pleasanter_Rds_MySQL_UserConnectionString: ${Implem_Pleasanter_Rds_MySQL_UserConnectionString}
  codedefiner:
    build:
      context: .
      dockerfile: ./CodeDefiner/Dockerfile
    container_name: codedefiner
    environment:
      Implem.Pleasanter_Rds_MySQL_SaConnectionString: ${Implem_Pleasanter_Rds_MySQL_SaConnectionString}
      Implem.Pleasanter_Rds_MySQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_MySQL_OwnerConnectionString}
      Implem.Pleasanter_Rds_MySQL_UserConnectionString: ${Implem_Pleasanter_Rds_MySQL_UserConnectionString}
volumes:
  my_data:
    name: ${COMPOSE_PROJECT_NAME:-default}_my_data_volume

変更点: MySQLの定義を削除

.env.tidb
MYSQL_ROOT_PASSWORD={{sa_password}}
Implem_Pleasanter_Rds_MySQL_SaConnectionString='Server=192.168.69.1;Port=4000;Database=test;UID=root;PWD={{sa_password}}'
Implem_Pleasanter_Rds_MySQL_OwnerConnectionString='Server=192.168.69.1;Port=4000;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD={{owner_password}}'
Implem_Pleasanter_Rds_MySQL_UserConnectionString='Server=192.168.69.1;Port=4000;Database=#ServiceName#;UID=#ServiceName#_User;PWD={{user_password}}'
env.mysql
MYSQL_ROOT_PASSWORD={{sa_password}}
Implem_Pleasanter_Rds_MySQL_SaConnectionString='Server=192.168.69.1;Port=3306;Database=test;UID=root;PWD={{'
Implem_Pleasanter_Rds_MySQL_OwnerConnectionString='Server=192.168.69.1;Port=3306;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=test'
Implem_Pleasanter_Rds_MySQL_UserConnectionString='Server=192.168.69.1;Port=3306;Database=#ServiceName#;UID=#ServiceName#_User;PWD=test'

変更点: Pleasanterをdockerコンテナで立ち上げるので、ローカルPCのdockerブリッジのIP(この場合は192.168.69.1) を指定しておく。あとポートを明示的に指定。
後で説明するがtidbではDBの初期化ができなかったので、.env.mysql.env.tidb.envに書き換えて利用する。

Rds.json
{
    "Dbms": "MySQL",
    "Provider": "Local",
    "SaConnectionString": null,
    "OwnerConnectionString": null,
    "UserConnectionString": null,
    "SqlCommandTimeOut": 0,
    "MinimumTime": 3,
    "DeadlockRetryCount": 4,
    "DeadlockRetryInterval": 1000,
    "DisableIndexChangeDetection": true,
    "SysLogsSchemaVersion": 2
}

変更点: なし

pleasanter.sql
create user 'Implem.Pleasanter_Owner'@'%' identified by {{owner_password}};
grant all on `Implem.Pleasanter`.* to 'Implem.Pleasanter_Owner'@'%' with grant option;
create user 'Implem.Pleasanter_User'@'%' identified by {{user_password}};
grant select, insert, update, delete, create routine, alter routine on `Implem.Pleasanter`.* to 'Implem.Pleasanter_User'@'%';

変更点: なし。ただしMySQLコンテナを利用しないため、このファイルの内容をMySQL、TiDBともにmysqlクライアントで接続して実行する。

CodeDefiner/Dockerfile
FROM implem/pleasanter:codedefiner

COPY app_data_parameters/ /app/Implem.Pleasanter/App_Data/Parameters/
ENTRYPOINT [ "dotnet", "Implem.CodeDefiner.dll" ]

変更点: MySQLコンテナの起動を削除

Pleasanter/Dockerfile
ARG VERSION=latest
FROM implem/pleasanter

COPY app_data_parameters/ App_Data/Parameters/
ENTRYPOINT [ "dotnet", "Implem.Pleasanter.dll" ]

変更点: MySQLコンテナの起動を削除

bohnenbohnen

失敗: TiDBに接続してCodeDefiner

最初、TiDBを起動してCodeDefinerを起動したらエラーを吐いて終了した。

まず、TiDB Playgroundを起動する。コンテナからアクセスできるように、コンテナのブリッジIPで起動する。

> tiup playground --host 192.168.69.1

Note: Version constraint  is resolved to v8.5.1. If you'd like to use other versions:

    Use exact version:      tiup playground v7.1.0
    Use version range:      tiup playground ^5
    Use nightly:            tiup playground nightly

Start pd instance: v8.5.1
Start tikv instance: v8.5.1
Start tidb instance: v8.5.1
Waiting for tidb instances ready
192.168.69.1:4000 ... Done
Start tiflash instance: v8.5.1
Waiting for tiflash instances ready
192.168.69.1:3930 ... Done

🎉 TiDB Playground Cluster is started, enjoy!

Connect TiDB:    mysql --host 192.168.69.1 --port 4000 -u root
TiDB Dashboard:  http://192.168.69.1:2379/dashboard
Grafana:         http://192.168.69.1:3000

起動したら、rootユーザーのパスワード設定、pleasanter.sqlの実行を行う。

alter user root@'%' identified by {{sa_password}};
source docker-entrypoint-initdb.d/pleasanter.sql;

この状態でCodeDefinerを起動すると、エラーが出力される。エラーは次の3つ。

  1. Implem.Pleasanter データベースの作成の失敗。
  • set sql_mode=ansi_quotes...;\ncreate database.... でエラーになっている。間の\nのあたりが怪しそうだが、この2行を別途ファイルに書いてsourceで実行してもエラーにならない。改行コードがおかしいのかな?
  • 暫定の回避策としては、個々のセッションでの指定ではなく、set global sql_mode=ansi_quotes として、グローバルで指定しておけば良さそうだ。
  1. alter table modify column で auto_increment
  • Pleasanterでは、テーブル定義の後にカラム変更でauto_incrementを付与しているが、TiDBではauto_incrementカラムは変更できない。 13テーブルくらい該当するため、mysqlで作成したテーブル定義をimportした方が楽だなと思った。最初からatuo_increment指定にしたら通るのだが、ORMの挙動だろうか。
  1. FullTextインデックスが作成できない
  • TiDBはFullTextインデックスに対応していない。これは対処方法はないが、インデックスなのでなくても動作するようだ。

これを回避するために、まずはMySQLでCodeDefinerを実行し、そのテーブル定義をTiDBにImportすることにした。

bohnenbohnen

CodeDefinerによるテーブルの初期化

AUTO_INCREMENTは後から変更ができないのが問題なので、CREATE TABLEに含めてしまえばTiDBでも問題がおこらない。プリザンターのログを見るとテーブル定義と属性変更は別々のクラスで実行されているようなので、ALTER TABLEしているのはORMの都合によるものなのではないかと思った。

<INFO> Tables.CreateTable: SysLogs
<ERROR> TablesConfigurator.Configure: [SysLogs]: MySqlConnector.MySqlException (0x80004005): Unsupported modify column: can't set auto_increment

修正も面倒そうなので、まずはその他に問題がないか確認することを優先し、一度MySQLにテーブルを作成して、それをTiDBに移行する方法をとった。

  1. まずMySQLを起動する。rootパスワードは .env.mysql に合わせて指定
docker run -d -p3306:3306 -e MYSQL_ROOT_PASSWORD={{sa_password}} mysql:8.4
  1. .env.mysql.env にコピー

  2. CodeDefinerを起動

docker compose run --rm codedefiner _rds /l "ja" /z "Asia/Tokyo"

これは正常終了する。

  1. dumplingを使ってMySQLからテーブル定義をエクスポート
tiup dumpling -h 192.168.69.1 -u root -P 3306 -p{{sa_password}} -o dump

実際にはこれは全データベースをエクスポートしているが、データが入っていないので実質テーブル定義のみ。

  1. lightningを使ってTiDBにインポート

lightningを使うには定義ファイルが必要。

lightning.toml
[lightning]
# Logging
level = "info"
file = "tidb-lightning.log"

[conflict]
strategy = "replace"

[tikv-importer]
# Configure the import mode
backend = "tidb"

[mydumper]
# Local source data directory
data-source-dir = "dump"

[tidb]
# Information of the target cluster
host = "192.168.69.1"
port = 4000
user = "root"
password = {{sa_password}}

lightningを起動する

tiup tidb-lightning --config lightning.toml

Starting component tidb-lightning: /Users/bohnen/.tiup/components/tidb-lightning/v8.5.0/tidb-lightning --config lightning.toml
Verbose debug logs will be written to tidb-lightning.log

+---+----------------------------------------------+-------------+--------+
| # | CHECK ITEM                                   | TYPE        | PASSED |
+---+----------------------------------------------+-------------+--------+
| 1 | Source data files size is proper             | performance | true   |
+---+----------------------------------------------+-------------+--------+
| 2 | the checkpoints are valid                    | critical    | true   |
+---+----------------------------------------------+-------------+--------+
| 3 | Cluster version check passed                 | critical    | true   |
+---+----------------------------------------------+-------------+--------+
| 4 | Lightning has the correct storage permission | critical    | true   |
+---+----------------------------------------------+-------------+--------+

問題なく取り込めたようだ

bohnenbohnen

Pleasanterの起動

今作ったTiDBのデータベースを下に、Pleasanterを起動する。

  1. dockerで立ち上げたMySQLをkillしておく
  2. .env.tidb.env にコピー
  3. Pleasanterを起動し、http://localhost:50001にアクセス
docker compose up -d pleasanter

パスワード変更ののち、トップ画面が出力される。チュートリアルを少し試した感じでは問題なさそう。

TiDB側の Imprem.Pleasanter.SysLogs にもログが記録されている。

mysql> select * from SysLogs;

+-------------------------+----------+-----+------------+---------+----------------------------+-------------------+------------+--------------------->
| CreatedTime             | SysLogId | Ver | SysLogType | OnAzure | MachineName                | ServiceName       | TenantName | Application         >
+-------------------------+----------+-----+------------+---------+----------------------------+-------------------+------------+--------------------->
| 2025-02-22 23:03:29.000 |        1 |   1 |         10 |    NULL | 5106161b51d8:Unix 6.6.51.0 | Implem.Pleasanter | NULL       | Implem.DefinitionAcc>
| 2025-02-22 23:03:29.067 |        2 |   1 |         10 |    NULL | 5106161b51d8:Unix 6.6.51.0 | Implem.Pleasanter | NULL       | Implem.DefinitionAcc>
| 2025-02-22 23:03:29.084 |        3 |   1 |         10 |    NULL | 5106161b51d8:Unix 6.6.51.0 | Implem.Pleasanter | NULL       | Implem.DefinitionAcc>
| 2025-02-22 23:03:36.578 |        4 |   1 |         10 |    NULL | 5106161b51d8:Unix 6.6.51.0 | Implem.Pleasanter | NULL       | Implem.DefinitionAcc>
...