dockerコンテナを使用せずに1台のマシンで複数のKnowledgeを立ち上げる

dockerコンテナを使用せずに、1台のマシンで複数のKnowledgeを立ち上げる方法を記載する。

# 概要

dockerを使用すれば、1台のマシンで複数のKnowledgeを立ち上げる事は容易であるが、各コンテナがtomcatを実行するためメモリの消費が激しい。

なるべくメモリを節約するため、1台のマシンでdockerを使用せずに複数のKnowledgeを立ち上げる。

# tomcat8のインストール

``` bash
apt update
apt install -y openjdk-8-jdk #必ずこれが完了してからtomcat8を入れる

apt install -y tomcat8

systemctl stop tomcat8
```

　関連記事
　https://qiita.com/panda1100/items/1718a6515a4ffa429bba

# knowledge 1.13.1のインストール

``` bash
# tomcat8のhome directoryに移動
cd /var/lib/tomcat8
# 複数のknowledgeを立ち上げるのに使用するディレクトリを作成
# dbは各knowledgeのdbファイルを格納する
# .app1, .app2, .app3は後ほど各knowledgeのbasePathに指定するディレクトリ
mkdir factory db .app1 .app2 .app3
chown tomat8:tomcat8 factory db .app1 .app2 .app3
# 複数のknowledgeを立ち上げるための準備をするディレクトリに移動
cd factory
# 元になるknowldge.warを取得
wget https://github.com/support-project/knowledge/releases/download/v1.13.1/knowledge.war
# 立ち上げる数の分、knowledge.warをコピーする
# コピー先のファイル名はコンテキストパスとして使用する
# 例 http://localhost:8080/app1
# 　 http://localhost:8080/app2
# 　 http://localhost:8080/app3
for app in app1 app2 app3
do
 cp knowledge.war $app.war
done
# 或いは、echo app1.war app2.war app3.war | xargs -n 1 cp -v knowledge.war
```

# 各Knowledgeの設定

複数のknowledgeを立ち上げるため、各warファイルを編集して各knowledge用の設定を書き込む。
まずは、warファイルから必要なファイルを抜き出す

``` bash
jar xf knowledge.war WEB-INF/classes/{appconfig.xml,connection.xml}
```

`appconfig.xml`は`systemName`,`basePath`,`databasePath`を編集する
`basePath`は先程作成した`/var/lib/tomcat8/.app1`を指定する
`databasePath`は`{user.home}`以下の`db`ディレクトリを指定する

``` xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app>
    <systemName>app1</systemName>
    <envKey>KNOWLEDGE_HOME</envKey>
    <time_zone>Asia/Tokyo</time_zone>
    <basePath>{user.home}/.app1</basePath>
    <indexPath>{base.path}/index/</indexPath>
    <tmpPath>{base.path}/tmp/</tmpPath>
    <databasePath>{user.home}/db/</databasePath>
    <slidePath>{base.path}/slide/</slidePath>
    <logsPath>{base.path}/logs/</logsPath>
    <uploadMaxMBSize>500</uploadMaxMBSize>
    <hashIterations>100</hashIterations>
    <languages>
        <language>
            <label>jp</label>
            <value>ja</value>
        </language>
        <language>
            <label>us</label>
            <value>en</value>
        </language>
    </languages>
    <addUserProcess>org.support.project.knowledge.logic.AddUserProcessLogic</addUserProcess>
    <afterLangSelectPage>/open.knowledge/list</afterLangSelectPage>
</app>
```

`connection.xml`は`URL`を編集する。ここでは`app1_db`に変更

``` xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<connectionConfig>
        <name>connection</name>
        <driverClass>org.h2.Driver</driverClass>
        <URL>jdbc:h2:tcp://localhost/./app1_db</URL>
        <user>sa</user>
        <password></password>
        <schema>public</schema>
        <maxConn>5</maxConn>
        <autocommit>false</autocommit>
</connectionConfig>
```

2つのファイルの編集が終わったらwarに書き込む。

``` bash
jar uf app1.war WEB-INF/classes/{appconfig.xml,connection.xml}
rm -rf WEB-INF # 不要なファイルを削除
```



続けてapp2, app3と作業する。(作業ディレクトリは`factory`)

``` bash
for app in app2 app3
do
  jar xf knowledge.war WEB-INF/classes/{appconfig.xml,connection.xml}
  sed -i "s@<systemName>knowledge</systemName>@<systemName>$app</systemName>@"  WEB-INF/classes/appconfig.xml
  sed -i "s@<basePath>{user.home}/.knowledge</basePath>@<basePath>{user.home}/.$app</basePath>@"  WEB-INF/classes/appconfig.xml
  sed -i "s@<databasePath>{base.path}/db/</databasePath>@<databasePath>{user.home}/db/</databasePath>@"  WEB-INF/classes/appconfig.xml

  sed -i "s@<URL>jdbc:h2:tcp://localhost/./knowledge_db</URL>@<URL>jdbc:h2:tcp://localhost/./${app}_db</URL>@"  WEB-INF/classes/connection.xml

  jar uf $app.war WEB-INF/classes/{appconfig.xml,connection.xml}
  rm -rf WEB-INF
done
```

設定の書き込みが終わったら、`/var/lib/tomcat8/webapps`以下にコピーする。(作業ディレクトリは`factory`)

その前に`/var/lib/tomcat8/work/Catalina/localhost`以下に不要なキャッシュが残っていれば削除する。work以下に不要なものが無い状態で以下を実行。

``` bash
cp app1.war app2.war app3.war ../webapps # /var/lib/tomcat8/webapps
```

最後に、tomcat8を起動する

``` bash
systemctl start tomcat8
```

warが展開されているか確認

``` bash
ls /var/lib/tomcat8/webapps
app1 app1.war app2 app2.war app3 app3.war
```

dbが作成されているか確認

``` bash
ls /var/lib/tomcat8/db
app1_db.mv.db app2_db.mv.db app3_db.mv.db
```

ブラウザで接続して確認

http://localhost:8080/app1
http://localhost:8080/app2
http://localhost:8080/app3

URIを`http://localhost:8080/ABC/app1`のようにしたい時は、warのファイル名を`ABC#app1.war`のようにしておくと良い。

ここまで来たら後はスクリプトで追加できるように。
確認もせず何も言わずにただだまって追加する漢なスクリプトをfactoryの下に`add`などで配置しておく。

``` bash
#!/bin/bash
cd /var/lib/tomcat8/factory
cp knowledge.war ${1}.war
jar xf knowledge.war WEB-INF/classes/{appconfig.xml,connection.xml}
sed -i "s@<systemName>knowledge</systemName>@<systemName>${1}</systemName>@"  WEB-INF/classes/appconfig.xml
sed -i "s@<basePath>{user.home}/.knowledge</basePath>@<basePath>{user.home}/.${1}</basePath>@"  WEB-INF/classes/appconfig.xml
sed -i "s@<databasePath>{base.path}/db/</databasePath>@<databasePath>{user.home}/db/</databasePath>@"  WEB-INF/classes/appconfig.xml
sed -i "s@<URL>jdbc:h2:tcp://localhost/./knowledge_db</URL>@<URL>jdbc:h2:tcp://localhost/./${1}_db</URL>@"  WEB-INF/classes/connection.xml
jar uf ${1}.war WEB-INF/classes/{appconfig.xml,connection.xml}
rm -rf WEB-INF
mkdir /var/lib/tomcat8/.${1}
chown tomcat8:tomcat8 /var/lib/tomcat8/.${1}
cp ${1}.war /var/lib/tomcat8/webapps
```

使い方

``` bash
cd /var/lib/tomcat8/factory
bash ./add SOME_NAME 
```