NextcloudにOnlyOfficeとElasticsearchを組み込んで最強のオンラインストレージサーバを構築する

# はじめに

ドキュメントをMarkdownで書く文化が浸透していれば全文検索可能なドキュメントサーバを構築するのはさほど困難ではないであろう。
が、問題はそうでないことである。

技術者ならMarkdownを使うかと思いたいが同僚やお付き合いのあるシステムベンダーを見てもそんな人は皆無に等しくほぼワードやエクセル、PDFという形でアウトプットしてくる。
そういう場合に布教活動を行うのも手だがMS Office文書などが取り扱えるサービスが構築できるならそのほうが手っ取り早いし皆に喜んでもらえる。

オンプレで構築するオンラインストレージサーバとしてはNextcloudが有名でオフィス文書を扱うためにOnlyOfficeと組み合わせたり、全文検索するためにElasticSearchを導入する方法は紹介されているものの、いかんせん情報が細切れだったり古かったりして簡単には動かなかった。
そこで[公式イメージ](https://github.com/ONLYOFFICE/docker-onlyoffice-nextcloud)を元にゴニョゴニョしたらなんとかできたので紹介したい。

https://github.com/higebobo/docker-nextcloud

# セットアップ

## Nextcloudのインストール

上記レポジトリからクローン

```shell
git clone https://github.com/higebobo/docker-nextcloud.git
```
データベースサーバの接続情報などは.envを作成・編集して変更できるがそのままデフォルト情報(Makefileの冒頭に記述)でビルドできる。
(GNU Makeが使えない場合はMakefileのタスクを参照してコマンドラインから実行すればよい)

```shell
make up
```

しばらくすると完了するのでブラウザでNextcloudにアクセスする(デフォルトではhttp://localhost:8080)

![FireShot Capture 007 - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/6644c1b6-d904-8543-dfd1-0b4c6b6c8425.png)

ユーザ名やパスワードは適当に入力して「ストレージとデータベース」をクリック

![FireShot Capture 008 - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/6050bd68-3466-2946-0151-50b6fb955291.png)

環境変数で設定したデータベースの情報を入力。最後のホストのところは`localhost`とか入れずに`db`とすること(docker-composeで指定したデータベースのサービス名)。

次にアプリをインストールする。

![FireShot Capture 009 - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/caeec4ab-8b80-bdb8-d815-53c8b7b1fd89.png)

「推奨アプリをインストール」をクリックしてしばらく待つと完了。

![FireShot Capture 010 - ダッシュボード - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/9b490984-e022-9436-cd7d-c8ac721cd3f5.png)

## OnlyOfficeの設定

Nextcloudのインストールが完了したのでOnlyOfficeの設定を行う。
ダッシュボードからやってもできるのだろうが、公式イメージで提供されているスクリプトを利用(Makefileのタスク参照)。

```shell
make onlyoffice
```

出力結果

```shell
+ docker exec -u www-data app-server php occ --no-warnings config:system:get trusted_domains
+ grep -q nginx trusted_domain.tmp
+ cat trusted_domain.tmp
+ wc -l
+ TRUSTED_INDEX=1
+ docker exec -u www-data app-server php occ --no-warnings config:system:set trusted_domains 1 --value=nginx
System config value trusted_domains => 1 set to string nginx
+ rm trusted_domain.tmp
+ docker exec -u www-data app-server php occ --no-warnings app:install onlyoffice
onlyoffice 7.3.0 installed
onlyoffice enabled
+ docker exec -u www-data app-server php occ --no-warnings config:system:set onlyoffice DocumentServerUrl --value=/ds-vpath/
System config value onlyoffice => DocumentServerUrl set to string /ds-vpath/
+ docker exec -u www-data app-server php occ --no-warnings config:system:set onlyoffice DocumentServerInternalUrl --value=http://onlyoffice-document-server/
System config value onlyoffice => DocumentServerInternalUrl set to string http://onlyoffice-document-server/
+ docker exec -u www-data app-server php occ --no-warnings config:system:set onlyoffice StorageUrl --value=http://nginx/
System config value onlyoffice => StorageUrl set to string http://nginx/
+ docker exec -u www-data app-server php occ --no-warnings config:system:set allow_local_remote_servers --value=true
System config value allow_local_remote_servers set to string true
```

管理画面からOnlyOfficeの設定が確認できる。

![FireShot Capture 011 - 設定 - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/d9f7530d-946d-7018-d028-4f5ab59af731.png)

## 全文検索の設定

ダッシュボード>アプリから`Full Text`を検索

![FireShot Capture 013 - アプリ - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/f5398215-a4c7-782f-2ff8-2f856a4d7b54.png)

以下を組み込む

* Full text search
* Full text search - Elasticsearch Platform
* Full text search - Files

ダッシュボード>設定から「全文検索」の設定画面を表示

![FireShot Capture 014 - 設定 - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/ade8407e-5498-ad32-5fc3-6ccd6c3c96e6.png)

以下を設定

* 検索プラットフォーム: Elasticsearch
* サーブレットのアドレス: http://elasticsearch:9200/
* インデックス: nextclud(任意の名称)
* アナライザトークナイザ: kuromoji_tokenizer

検索インデックスの作成

```shell
make index
```

出力結果

```
Options: []
Memory:
┌─ Indexing  ────
│ Action:
│ Provider:                      Account:
│ Document:
│ Info:
│ Title:
Options: []

...略

┌─ Results ────
│ Result:     30/30
│ Index: files:18
│ Status: ok
│ Message: {"_index":"nextcloud","_type":"_doc","_id":"files:18","_version":1,
│ "result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":
│ 29,"_primary_term":1}
└──
┌─ Errors ────
│ Error:      0/0
│ Index:
│ Exception:
│ Message:
│
│
└──
## x:first result ## c/v:prec/next result ## b:last result
## f:first error ## h/j:prec/next error ## d:delete error ## l:last error
## q:quit ## p:pause
```

エラーが0/0となっているので成功しているが最初ここが30/30とかになってうまく行かなかった。
その場合は

```shell
make index-init
```

とか

```shell
make index-reset
```

とかすると幸せになれるかもしれない。

なお、インデックスの作成は文書の登録のたびに実行する必要があるのでバッチで組み込むなどして定期実行するようにする。

# 動作確認

右上の検索アイコンから`self-hosted`と入力してみる(なぜこのキーワードなのかは後述)。

![FireShot Capture 015 - ダッシュボード - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/55892e02-0e81-1b1b-ae5d-d12efeefccae.png)

そしてこちらが編集可能の画面

![FireShot Capture 016 - ファイル - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/36f738ac-18f7-2c14-a192-673ca6bb4682.png)

今回の例としては初期に組み込まれている文書から検索したが、日本語の検索ももちろんできる。
試しに「レンタル」という文字が入力されているエクセル文書をアップロードしてインデックス作成後に検索すると正しく検索できている。

![FireShot Capture 017 - ファイル - Nextcloud - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/d95fa628-e471-40ab-077b-0075671d6fad.png)

なお、オフィス文書を表示するときに「ONLYOFFICEに接続できません。管理者に相談してください」と出る場合は`onlyoffice-server`の起動に時間がかかっているのでしばらく待って再度アクセスする。

# 最後に

docker-composeを利用することで複数のサービス(Nginx/Nextcloud(PHP)/Mariadb/OnlyOffice/ElasticSearch/Kibana)のインストールが一発でできるのがこの上なく便利であるし移植性も高い。
以前はこういうのを一つ一つインストール・設定(さらに動作確認)していたので新規に構築するときやサーバを更新・移転する場合など極めて気が重くなる作業だった。

最後にdocker-compose.yamlを掲載しておく。
私は極力ポートは開けないし、今回はkibanaも重たくなるので利用しないのでコメントアウトしているが好みに応じて活用してもらえればよいかと思う。

```yaml
version: "3.7"

services:
  app:
    image: nextcloud:23.0-fpm-alpine
    container_name: ${APP_CONTAINER}
    restart: always
    environment:
      - extra_params="--o:ssl.enable=false"
    depends_on:
      - db
      - onlyoffice-document-server
      - elasticsearch
    volumes:
      - "$PWD/data/web:/var/www/html"
  db:
    image: mariadb:10.7-focal
    container_name: ${DB_CONTAINER}
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed
    restart: always
    volumes:
      - "$PWD/data/db:/var/lib/mysql"
    #ports:
    #  - ${MYSQL_PORT}:3306
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
  onlyoffice-document-server:
    image: onlyoffice/documentserver:7.0
    container_name: ${DOC_CONTAINER}
    restart: always
    volumes:
      - "$PWD/data/log/onlyoffice:/var/log/onlyoffice"
      - "$PWD/data/onlyoffice:/var/www/onlyoffice/Data"
  nginx:
    image: nginx:1.21
    container_name: ${WEB_CONTAINER}
    restart: always
    ports:
      - "${WEB_PORT}:80"
      #- "${SSL_PORT}:443"
    volumes:
      - "$PWD/config/nginx.conf:/etc/nginx/nginx.conf"
      - "$PWD/data/web:/var/www/html"
  elasticsearch:
    build: ./elasticsearch
    container_name: ${SEARCH_CONTAINER}
    restart: always
    environment:
      - discovery.type=single-node
#    ports:
#      - "${SEARCH_PORT}:9200"
#      #- "${ELASTICSEARCH_NODE_PORT}:9300"
#  kibana:
#    image: docker.elastic.co/kibana/kibana:7.17.0
#    container_name: ${MONITOR_CONTAINER}
#    restart: always
#    depends_on:
#      - "elasticsearch"
#    ports:
#      - "${MONITOR_PORT}:5601"
```

elasticsearch/Dockerfile (kibanaを使う場合はelasticsearchとバージョンは合わせること)

```dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:7.17.0

RUN elasticsearch-plugin install --batch ingest-attachment &&\
    elasticsearch-plugin install --batch analysis-kuromoji &&\
    elasticsearch-plugin install --batch analysis-icu
```

# リンク

* [ONLYOFFICE/docker\-onlyoffice\-nextcloud](https://github.com/ONLYOFFICE/docker-onlyoffice-nextcloud)
* [docker composeを使ってonlyofficeが使用できるnextcloudを構築する \| mebee](https://mebee.info/2021/05/25/post-34497/)