Google Pagespeed Insightsのスコアがすこぶる悪い。
adsenseのせいもあるが、基本的に読み込みが遅い。
このページの前提
モバイルに限って若干の改善は見られたがPCではほぼ変化なし。
この実験から言えること
以降、3系での手順だがほぼ同じ。
・NASのアップデートなど、再起動時にDockerがうまく起動しないことがあるが、その解決手順をDocker上のGROWIに書いていると詰む。
我ながらアホ。
同じ轍を踏まないためのメモ
sudo docker ps -a を見て停止や再起動ループの状態を確認する。restart: unless-stopped を付けていても、依存先(mongo / elasticsearch)より先にappが起動しようとして失敗することがある。Markdown で書けるオープンソースの Wiki システム"GROWI"をSynology NASのDocker上にインストールする。
今回はdocker-composeを使ってインストールする。
growi-docker-compose - The fastest way to boot All-in-One GROWI
どうせなので、HackMD(CodiMD) integrationもセットで導入。
基本は公式の手順に従う。NASにSSHして以下のコマンドを入力。Synology NASへのSSH
$ git clone https://github.com/weseek/growi-docker-compose.git growi
$ cd growi
$ docker-compose up
これで、NASのIP:3000にアクセスすると動くらしいのだが、環境の問題でそのままでは動かなかった。
ポート指定の意味
127.0.0.1:3000:3000 は「ホストのループバックからだけ3000番に繋ぐ」指定で、LANの他端末からは見えない。3000:3000 にするとホストの全インターフェースで待ち受ける。docker-compose up は初回にイメージのビルドが走るので数分〜十数分かかる。止まったように見えても待つ。今回はグローバルからも参照できるようにするために、ローカルアクセスの制限を取り除く。
Before
services:
app:
ports:
- 127.0.0.1:3000:3000
After
services:
app:
ports:
- 3000:3000
メモリを食うので多めに与える。
ES_JAVA_OPTS の意味
-Xms2g -Xmx2g はElasticsearchが使うJVMヒープの最小値と最大値をどちらも2GBに固定する指定。両方を揃えるとヒープの伸縮が減り、動きが安定する。bootstrap.memory_lock=true と ulimits.memlock はセットで、Elasticsearchのメモリをスワップさせないための設定。片方だけ書いても効かない。environment:
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
以下、我が家の最終的に動作した設定。
主要な環境変数の読み方
PASSWORD_SEED=changeme はパスワードのハッシュに混ぜる種。初回起動後に変えると既存ユーザーがログインできなくなるので、決めたら変えない。MONGO_URI / ELASTICSEARCH_URI はコンテナ名(mongo / elasticsearch)で名前解決させる。composeのネットワーク内で解決されるので、IPは書かない。FILE_UPLOAD=local はアップロードファイルをサーバ側ボリュームに置く設定。/data にマウントした /volume1/docker/growi/growi_data が実体になる。S3を使わないならこのままでいい。HACKMD_URI はブラウザから見えるアドレス、HACKMD_URI_FOR_SERVER はGROWIコンテナから見たアドレス。外向けと内向けを別々に書くのがポイントで、ここを同じにするとコンテナ間の連携が失敗する。MATHJAX=1 は数式表示、FORCE_WIKI_MODE は公開/非公開の固定に使う。コメントアウトのままでも動く。command: の dockerize -wait ... は、mongoとelasticsearchが起動するまでappの起動を待たせる仕掛け。NASが遅いと270秒でも足りないことがあるので、タイムアウトは長めにしておく。version: '3'
services:
app:
build:
context: .
dockerfile: ./Dockerfile
ports:
- 3000:3000 # localhost only by default #<=ローカル以外のアクセスを許す
links:
- mongo:mongo
- elasticsearch:elasticsearch
depends_on:
- mongo
- elasticsearch
environment:
- MONGO_URI=mongodb://mongo:27017/growi
- ELASTICSEARCH_URI=http://elasticsearch:9200/growi
- PASSWORD_SEED=changeme
# - FILE_UPLOAD=mongodb # activate this line if you use MongoDB GridFS rather than AWS
- FILE_UPLOAD=local # activate this line if you use local storage of server rather than AWS
- MATHJAX=1 # activate this line if you want to use MathJax
# - PLANTUML_URI=http:// # activate this line and specify if you use your own PlantUML server rather than public plantuml.com
- HACKMD_URI=https://hackmd.nagoya88.net #<=アクセスにはサブドメインを
- HACKMD_URI_FOR_SERVER=http://hackmd:3000 # activate this line and specify HackMD server URI which can be accessed from this server container
# - FORCE_WIKI_MODE='public' # activate this line to force wiki public mode
# - FORCE_WIKI_MODE='private' # activate this line to force wiki private mode
command: "dockerize
-wait tcp://mongo:27017
-wait tcp://elasticsearch:9200
-timeout 270s #<=タイムアウトを長めに
npm run server:prod"
restart: unless-stopped
volumes:
- /volume1/docker/growi/growi_data:/data #<=ボリュームをローカルに
mongo:
image: mongo:3.6
restart: unless-stopped
volumes:
- /volume1/docker/growi/mongo_configdb:/data/configdb #<=ボリュームをローカルに
- /volume1/docker/growi/mongo_db:/data/db #<=ボリュームをローカルに
elasticsearch:
build:
context: ./elasticsearch
dockerfile: ./Dockerfile
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms2g -Xmx2g" #<=ボリュームをローカルに
ulimits:
memlock:
soft: -1
hard: -1
restart: unless-stopped
volumes:
- /volume1/docker/growi/es_data:/usr/share/elasticsearch/data #<=ボリュームをローカルに
- /volume1/docker/growi/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml #<=ボリュームをローカルに
"/docker/growi/examples/integrate-with-hackmd/docker-compose.override.yml"を"/docker/growi/docker-compose.override.yml"にコピーして編集。
version: '3'
services:
##
# HackMD(CodiMD) container
# see https://github.com/hackmdio/codimd#configuration
#
hackmd:
build:
context: ./hackmd
environment:
- GROWI_URI=https://wiki.nagoya88.net #<=アクセスにはサブドメインを
- CMD_DB_URL=mysql://hackmd:hackmdpass@mariadb:3306/hackmd
- CMD_CSP_ENABLE=false
ports:
- 3100:3000 # localhost only by default #<=リバースプロキシは3100に
depends_on:
- mariadb
restart: unless-stopped
##
# MariaDB
# see https://hub.docker.com/_/mariadb/
mariadb:
image: mariadb:10.3
command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci
environment:
- MYSQL_USER=hackmd
- MYSQL_PASSWORD=hackmdpass
- MYSQL_DATABASE=hackmd
- MYSQL_RANDOM_ROOT_PASSWORD=true
restart: unless-stopped
volumes:
- /volume1/docker/growi/mariadb_data:/var/lib/mysql #<=ボリュームをローカルに
/docker/growi/elasticsearch/Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:6.6.1
LABEL maintainer Yuki Takei <yuki@weseek.co.jp>
RUN bin/elasticsearch-plugin install analysis-kuromoji
RUN bin/elasticsearch-plugin install analysis-icu
/docker/growi/elasticsearch/config/elasticsearch.yml
http.host: 0.0.0.0
# for elasticsearch-head
http.cors.enabled: true
http.cors.allow-origin: "*"
cluster.routing.allocation.disk.threshold_enabled: false #<=NASのストレージ残量が減るとElasticSearchがエラーを吐くのを防止
以上の設定を行ったうえで、GROWIとHackMDのアドレスそれぞれのサブドメインをhttps-portalでリバースプロキシで転送すれば自宅外からも動作する。
設定ファイルまわりの補足
cluster.routing.allocation.disk.threshold_enabled: false は、ディスク残量が減ったときにElasticsearchがシャード配置を止めて読み取り専用になるのを防ぐ設定。空き容量の少ないNASでは実質必須。ただし残量を無視して書き込み続けるので、ストレージの監視は別途必要。http.cors.enabled: true と http.cors.allow-origin: "*" は elasticsearch-head のような外部ツールから叩くための設定。9200番をLANに晒す前提になるので、使わないならこの2行は消しておく。analysis-kuromoji と analysis-icu を入れている。これが無いと日本語の全文検索が実用にならない。$ docker-compose up
これだけで起動するはずだが、うまくいかない場合はこちらを参照。
ちなみにSynology NASではCUIでのDocker-composeの作業もGUIには反映される。(各コンテナの状況のみ。composeの状況は見えない)
起動・停止の基本操作
docker-compose up はフォアグラウンドで動く。SSHを切ると止まるので、常用するなら docker-compose up -d でバックグラウンド起動にする。docker-compose up -d をもう一度実行すると、差分だけ作り直される。down はコンテナを消すが、ボリューム(/volume1/docker/growi 配下)は残る。latest を追うと、ある日突然起動しなくなる。Synology Dockerで遭遇したエラー対策
/Knowledge/Synology/Docker/Error
※ 本ページのAmazonリンクにはアフィリエイトタグ(toobf6-22)が付いている。
🤖 このページにはAIエージェント(ノア)による編集・加筆が含まれます。内容の正確性は保証できないため、重要な判断は一次情報でご確認ください。