プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

QNAP の Container Station で Pleasanter を動かす

伊勢IT交流会によく参加していただいてる方からプリザンター(Pleasanter)というキーワードを聞いていて、ちょっと興味があったのですが、なかなか手を出す機会がありませんでした。ざっくりした理解としては kintone っぽいことが、OSS でできるというイメージのものです。

先日、

が発売になったのを知ったので、これはいいチャンスと思い、早速購入して試してみることにしました。

試すには動作するものを用意しないといけないんですが、 QNAP の Container Station (Docker) を利用することにしたら、意外と手間取ったので、その顛末をメモっておこうと思います。

なお、試した際の環境は下記の通りでした。

  • QNAP TS-262
  • QTS QTS : 5.2.3.3006
  • Container Station : 3.0.9.1038 (2024/11/08)

Docker で動かす方法

Docker で動かすのは、こちらの公式

pleasanter.org

にある説明の通り進めれば問題なさそうです。若干、書き方がわかりにくいきらいがありますが、要は

  • .env
  • docker-compose.yml

の 2つを同じディレクトリに用意しておいて、コマンドをたたけば起動する、ということのようです。

QNAP の Container Station で動かす場合

さて問題は QNAP の Container Station で動かす場合です。 Container Station の『アプリケーションの作成』などを使えば、 docker-compose.yml の内容を指定してコンテナ群を起動することができるのですが、このとき、環境変数を指定するファイルを受け渡す方法がありません。

となると、どうやって Container Station からアプリケーションを作成して、起動や停止すればいいんだろうか?

しかも、公式の説明をよく読むとわかるのですが、 codedefiner はDBを初期化する際に一度動かすだけです(なので、Pleasanter の起動は docker compose up -d plesanter とサービス名 pleasanter のみを指定した起動方法になっています)。

FAQ:CodeDefinerとは | Pleasanter

しかし、QNAP の Container Station から起動する場合は、 docker-compose.yml に書かれているサービスがすべて起動されてしまいます(当然、依存関係の順番は有効ですが)。

つまり、 codedefienr が起動停止のたびに呼ばれてしまうということです。仮に実害がないとしても嫌ですね。

さて、どうしたものか?

解決方法

調べてみると、似たような悩みがあるようで、

Pleasanter 1.4.8.1をDocker Composeで動かす - とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

こちらの記事にいい方法が載ってました。要は、 db と Pleasanter の docker-compose.yml と codedefiner の docker-compose.yml に分けるというやり方です。

この考え方を元にいろいろと試行錯誤した結果、一部 NAS にログインしてコマンドラインで操作することで QNAP の Container Station で起動させることができました。

具体的な手順は次の通りです。

まずは、 Container Station で Pleasanter を含むアプリケーションを作成します。

この時 GUI で入力した中身( docker-compose.yml になります)は

services:
  db:
    container_name: postgres
    image: postgres:16
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB
      - POSTGRES_HOST_AUTH_METHOD
      - POSTGRES_INITDB_ARGS
    volumes:
      - type: volume
        source: pg_data
        target: /var/lib/postgresql/data
  pleasanter:
    container_name: pleasanter
    image: implem/pleasanter:1.4.13.0
    depends_on:
      - db
    ports:
      - '50001:8080'
    environment:
      Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString}
      Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString}
      Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString}

volumes:
  pg_data:
    name: ${COMPOSE_PROJECT_NAME:-default}_pg_data_volume

のように、データベースと Pleasanter のみとしておきます。また、各種情報は環境変数(.env ファイル)から与えるように定義しておきます。

これで、『作成』ボタンを押すと、アプリケーションの作成には成功しますが、こんな感じになり、正しく起動しません。

もちろん、 codedefiner は定義していないですし、環境変数もないので当然ですね。念のため、次に進む前に pleasanter コンテナを停止しておきます。

次に、 NAS に SSH でログインします。まずは、作成したアプリケーションフォルダに移動し、ここに codedefiner の定義を書いた docker-compose.codedefiner.yml ファイルと .env ファイルをコピーしておきます。

[user1@nas01 ~]$ cd /share/qnapData/container-station-data/application/pleasanter-test7/
[user1@nas01 pleasanter-test7]$ cp ~/work/docker/pleasanter-test/docker-compose.codedefiner.yml .
[user1@nas01 pleasanter-test7]$ cp ~/work/docker/pleasanter-test/env ./.env

あらかじめ、ログインユーザーのホームディレクトリにこれらのファイルを置いておきました。中身は次の通りです。

docker-compose.codedefiner.yml ファイル

services:
  codedefiner:
    container_name: codedefiner
    image: implem/pleasanter:codedefiner
    depends_on:
      - db
    command: "_rds /y /l \"ja\" /z \"Asia/Tokyo\""
    environment:
      Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString}
      Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString}
      Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString}

.env ファイル

POSTGRES_USER=postgresadmin
POSTGRES_PASSWORD=postgresAdmin
POSTGRES_DB=pleasanterdb
POSTGRES_HOST_AUTH_METHOD=scram-sha-256
POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256 --encoding=UTF-8"

Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString='Server=db;Database=pleasanterdb;UID=postgresadmin;PWD=postgresAdmin'
Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString='Server=db;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=postgresOwner'
Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString='Server=db;Database=#ServiceName#;UID=#ServiceName#_User;PWD=postgresUser'

上記の .env ファイルの中身は参考なので、適宜変更してください。コピー後はこんな感じになります。

[user1@nas01 pleasanter-test7]$ ls -laF
total 24
drwxrwxrwx 2 admin      administrators 4096 2025-03-04 12:24 ./
drwxr-xr-x 5 admin      administrators 4096 2025-03-04 12:20 ../
-rw-r--r-- 1 user1 everyone        545 2025-03-04 12:24 docker-compose.codedefiner.yml
-rw-rw-rw- 1 admin      administrators  206 2025-03-04 12:20 docker-compose.resource.yml
-rw-rw-rw- 1 admin      administrators  905 2025-03-04 12:20 docker-compose.yml
-rw-r--r-- 1 user1 everyone        582 2025-03-04 12:24 .env
[user1@nas01 pleasanter-test7]$ 

この docker-compose.yml はさきほど GUI で入力した中身から Container Station が自動的に作成したものになります。

この状態から、 codedefiner を実行します。

[user1@nas01 pleasanter-test7]$ docker compose -f docker-compose.yml -f docker-compose.codedefiner.yml run --rm codedefiner
[+] Creating 1/1
 ✔ Container postgres  Recreated                                                                                                                                                                                                    1.0s 
[+] Running 1/1
 ✔ Container postgres  Started                                                                                                                                                                                                      1.5s 
<INFO> Starter.Main: Implem.CodeDefiner 1.4.13.0
<INFO> RdsConfigurator.CreateDatabase: Implem.Pleasanter
<INFO> UsersConfigurator.Execute: Implem.Pleasanter_Owner
<INFO> UsersConfigurator.Execute: Implem.Pleasanter_User
<INFO> SchemaConfigurator.Configure: Implem.Pleasanter
<INFO> Configurator.OutputLicenseInfo: 
ServerName: db
Database: pleasanterdb
Deadline: 01/01/0001
Licensee: 
Users: 0
<INFO> Configurator.OutputLicenseInfo: This edition is "Community Edition".
(中略)
<INFO> Tables.CreateTable: Wikis_history
<INFO> PrivilegeConfigurator.Execute: Implem.Pleasanter_Owner
<INFO> PrivilegeConfigurator.Execute: Implem.Pleasanter_User
<SUCCESS> Starter.ConfigureDatabase: Database configuration has been completed.
<SUCCESS> Starter.Main: All of the processes have been completed.
[user1@nas01 pleasanter-test7]$ 

ここでは -f オプションを使うことで、もともとの docker-compose.yml に docker-compose.codedefiner.yml を結合して呼び出すことで、 codedefiner を簡単に起動できるようにしています。

なお、この時点で、 Container Station をみると、

のようになっており、 codedefiner が依存してたため、既に postgres が動いています。

ここまで出来たら、次はコマンドラインから、 pleasanter を一度起動します。

[user1@nas01 pleasanter-test7]$ docker compose up -d pleasanter
[+] Running 2/2
 ✔ Container postgres    Running                                                                                                                                                                                                    0.0s 
 ✔ Container pleasanter  Started                                                                                                                                                                                                    2.9s 
[user1@nas01 pleasanter-test7]$ 

このときは必ず up サブコマンドを使う必要があります。 up を使うと、コンテナの再作成が行われて、環境変数が確実に反映されます。

詳しくは上記などを確認してください。

なので、もし、コマンドラインから up するまえに、 QNAP のコンソールから Pleasanter コンテナの起動を行っても、環境変数が反映されないため、正しく実行できないと思います(推測ですが docker compose start とかで呼び出しているんじゃないかな?)。

ここまでできたら、ブラウザで http: // nasのIPアドレス:50001 にアクセスすると

こんな風にログイン画面が表示されます。

ここまでやって、コンテナが起動できるようになったら、あとは、QNAP の Container Station で起動・停止ができるようになります。ステータスもちゃんと反映されています。

ただ、試していた時の印象としては Container Station への状態の反映は遅いようです。表示がおかしいなと思ったら一度 Containser Station を終了して、再度呼び出すのも有効かと思います。

注意

QNAP の Container Station から Pleasanter を操作する場合、アプリケーションの『再作成』を使わないようにする必要があります。

Container Station から再作成を行うと、一度アプリケーションフォルダが削除されて、当初の docker-compose.yml ファイル( Container Station の GUI で入力した中身)を使って再度フォルダから作成します。当然、コピーした .env ファイルも消えてしまうので、正しく起動できなくなります。

あと、 pleasanter に限った話ではなく Container Station の使い方の話なのですが、アプリケーションを削除してやり直したいこともあると思います。このとき、

のようにチェックを入れると、名前付き volume も消えてしまうので、消してもいいやつかどうか確認してからやってください(デフォルトはチェックが入っていません)。

参考情報

今回の作業に当たっていろいろと調べたので、ついでに参考になりそうなものも載せておきます。

(参考)失敗例

QNAP の Container Station でアプリケーションを作成する際に、

services:
  db:
    container_name: postgres-tmp
    image: postgres:16
    environment:
      - POSTGRES_USER=postgresadmin
      - POSTGRES_PASSWORD=postgresAdmin
      - POSTGRES_DB=pleasanterdb
      - POSTGRES_HOST_AUTH_METHOD=scram-sha-256
      - POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256 --encoding=UTF-8"
    volumes:
      - type: volume
        source: pg_data
        target: /var/lib/postgresql/data
  pleasanter:
    container_name: pleasanter-tmp
    image: implem/pleasanter:1.4.13.0
    depends_on:
      - db
    ports:
      - '50002:8080'
    environment:
      Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: 'Server=db;Database=pleasanterdb;UID=postgresadmin;PWD=postgresAdmin'
      Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: 'Server=db;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=postgresOwner'
      Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: 'Server=db;Database=#ServiceName#;UID=#ServiceName#_User;PWD=postgresUser'
  codedefiner:
    container_name: codedefiner-tmp
    image: implem/pleasanter:codedefiner
    depends_on:
      - db
    environment:
      Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: 'Server=db;Database=pleasanterdb;UID=postgresadmin;PWD=postgresAdmin'
      Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: 'Server=db;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=postgresOwner'
      Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: 'Server=db;Database=#ServiceName#;UID=#ServiceName#_User;PWD=postgresUser'
volumes:
  pg_data:
    name: ${COMPOSE_PROJECT_NAME:-default}_pg_data_volume

のように .env を使わず済むように定義して作成しました。

その後、コンソールにログインして、コマンドラインから、 codedefiner による初期化をおこなおうとして、

[user1@nas01 pleasanter-blog]$ docker compose run --rm codedefiner _rds /y /l "ja" /z "Asia/Tokyo"

としてみると、

[+] Creating 1/0
 ✔ Container postgres-tmp  Created                                                                                                                                                                                                  0.0s 
[+] Running 1/1
 ✔ Container postgres-tmp  Started                                                                                                                                                                                                  1.4s 
<INFO> Starter.Main: Implem.CodeDefiner 1.4.13.0
<ERROR> Starter.TryOpenConnections: [-1] Name or service not known

Abort. Press any key to close.
[user1@nas01 pleasanter-blog]$ 

となり、失敗してしまいました。うまくいかないもんですね。

(参考)Rds.json とは

公式の docker の手順のページの先頭付近ででてくる Rds.json って何だろう?と思っていたのですが、この記事

Dockerイメージを使用しパラメータを既定値から変更して起動する | Pleasanter

を見ると、 pleasanter のコンテナ内にあるファイルのことみたいです。

なお、公式の docker の手順のページの意図は、接続文字列についての詳しい説明は Rds.json についての解説ページを見てくれ、ということのようでして、 docker で起動するだけなら直接このファイルを変更する必要はないようです(現に動きましたしね)。

ついでに、 pleasanter が動作した後、コンテナに入って、

[user1@nas01 pleasanter-test]$ docker exec -it pleasanter /bin/bash
root@deaf5157c5a8:/app# 

下記のディレクトリを表示すると

root@deaf5157c5a8:/app/App_Data/Parameters# ls
Api.json                BinaryStorage.json  ExtendedColumnDefinitions  ExtendedScripts        GroupChildren.json  Mail.json             OutputCache.json   Reminder.json  Session.json      Validation.json
Authentication.json     CustomApps.json     ExtendedFields             ExtendedServerScripts  GroupMembers.json   Migration.json        Parameter.json     Script.json    Site.json         Version.json
AutoTestSettings.json   Dashboard.json      ExtendedHtmls              ExtendedSqls           History.json        Mobile.json           Permissions.json   Search.json    SitePackage.json
BackgroundService.json  Deleted.json        ExtendedNavigationMenus    ExtendedStyles         Kvs.json            NavigationMenus.json  Rds.json           Security.json  SysLog.json
BackgroundTask.json     ExtendedAutoTest    ExtendedPlugins            General.json           Locations.json      Notification.json     Registration.json  Service.json   User.json
root@deaf5157c5a8:/app/App_Data/Parameters# 

ちゃんと Rds.json がありますね。中身をみるとこんな感じでした。

root@deaf5157c5a8:/app/App_Data/Parameters# cat Rds.json 
{
  "Dbms": "PostgreSQL",
  "Provider": "Local",
  "SaConnectionString": null,
  "OwnerConnectionString": null,
  "UserConnectionString": null,
  "SqlCommandTimeOut": 0,
  "MinimumTime": 3,
  "DeadlockRetryCount": 4,
  "DeadlockRetryInterval": 1000,
  "DisableIndexChangeDetection": true,
  "SysLogsSchemaVersion": 1
}
root@deaf5157c5a8:/app/App_Data/Parameters# 

まとめ

docker で起動できるのですぐだろうと思っていたら、意外と手間がかかってしまいました。でも、これで Container Station でも動かせることがわかったので、いろいろと試していきたいと思います。