Gitbook の環境を Dockerで作った
しばらくきちんとしたドキュメント作成から遠ざかっていたのだけど、仕様書なるものを書く事になった。
基本的に文章を書くのは Markdown 形式に寄せていくようにしているので Gitbook を使うことにした。最終的に PDF にすることも簡単であろうと。
しかし、PDF 出力でハマった。その記録。
要件
目的はシステムの仕様書を書くということを踏まえ次の要件で環境を作ることにした。
実現方法の検討
1. Markdownで記述できること
「1. Markdown で記述できること」は Gitbook を採用した時点で満たせる。
最初から Gitbook を使うつもりだったので、検討するまでもない。
ただ、ドキュメントの量が大きくなってくるとビルドに時間がかかりそうなのが気がかりだったので代替プロダクトを一応探してみた。
mdBookという Rust 製の Gitbook クローンを見つけたのだけど、mdBook 自体も言語から発展途上感が強かったので、今回は見送った。
で、当初の方針通り Gitbook を採用して進めることとした。
2. UMLも記載したい
これについては Gitbook のプラグインで解決できそうなので、どれを使うかということで探した。
mermaidを利用したものがお手軽で良さそうだったのだけど、クラス図をサポートできるものが見つからなかったので PlantUMLを利用したもので検討した。
PlantUML を利用するプラグインはいくつもある。ググってすぐ出てきたのは、plantumlなのだけど、それを改良したっぽい umlを使って見ることにした。
動作はするのだけど、gitbook serve
で使っていると、UML の出力が遅くて快適に使えない。PlantUML で UML をレンダリングする際に Java でできた PlantUML を動かすために JVM の起動から始まるのが遅い原因だと思われる。
そこで、PlantUML サーバをつかって UML をレンダリングするタイプのplantuml-cloudを使ってみることにした。狙い通り UML のレンダリングは速くなった。 速度改善と同時に PlantUML に必要な graphvizのインストールも不要になった。 オフライン時も使えるようにしたいのでローカルで PlantUML のサーバである plantuml-serviceを動かすことにした。Docker イメージも提供されているので、次の Docker コンテナを動かす Docker Compose ファイルを作った。
- plantuml-service
- nginx
- Giitbook
nginx は plantuml-service をリバースプロキシするために入れている。というのも plantuml-service の待受ポート番号(1608)と plantuml-cloud の接続ポート番号(80) が一致しておらず、変更もできなかったのだ。それで仕方なくリバプロして Gitbook からのリクエストを受けられるようにした。
docker-compose.yml は次の通り。
version: "2.2" services: plantuml: image: 'bitjourney/plantuml-service:1.3.3' nginx: image: nginx:alpine volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - plantuml gitbook: image: hero/docker-gitbook:latest volumes: - ./gitbook:/gitbook - ./dest:/gitbook_dest ports: - 4000:4000 depends_on: - nginx command: 'serve'
2018/11/08追記 plantuml-cloudに送っていたプルリクがマージされ、ポート番号が指定できるようになった。これに伴い nginx によるリバプロは不要になり、次の docker-compose.yml のように plantuml と gitbook だけでよくなった。
version: "2.2" services: plantuml: image: 'bitjourney/plantuml-service:1.3.3' gitbook: image: hero/docker-gitbook:latest volumes: - ./gitbook:/gitbook - ./dest:/gitbook_dest ports: - 4000:4000 depends_on: - plantuml command: 'serve'
この環境でplantuml-cloudを使うには次のように book.json で plantuml-cloud を設定する。
{ "plugins": ["plantuml-cloud"], "pluginsConfig": { "plantuml-cloud": { "protocol": "http", "host": "plantuml", "port": 1608 } } }
3. PDFで出力できること
Gitbook の PDF 出力は calibreに依存している。 calibre をインストールしている他の Docker イメージを参考にしながら次のような Dcokerfile を作った。
FROM node:10.12.0-alpine LABEL maintainer="HeRoMo" ENV GLIBC_VERSION 2.28-r0 RUN apk add --update curl && \ curl -Lo /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \ curl -Lo glibc.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk" && \ curl -Lo glibc-bin.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk" && \ apk add glibc-bin.apk glibc.apk && \ /usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib && \ echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \ apk del curl && \ rm -rf glibc.apk glibc-bin.apk /var/cache/apk/* ENV LD_LIBRARY_PATH $LD_LIBRARY_PATH:/opt/calibre/lib ENV PATH $PATH:/opt/calibre/bin ENV CALIBRE_INSTALLER_SOURCE_CODE_URL https://raw.githubusercontent.com/kovidgoyal/calibre/master/setup/linux-installer.py RUN apk update && \ apk add --no-cache --upgrade \ bash \ ca-certificates \ gcc \ mesa-gl \ python \ qt5-qtbase-x11 \ wget \ xdg-utils \ libxcomposite \ xz && \ wget -O- ${CALIBRE_INSTALLER_SOURCE_CODE_URL} | python -c "import sys; main=lambda:sys.stderr.write('Download failed\n'); exec(sys.stdin.read()); main(install_dir='/opt', isolated=True)" && \ rm -rf /tmp/calibre-installer-cache RUN yarn global add gitbook-cli svgexport COPY ./start.sh /usr/bin/ RUN chmod 755 /usr/bin/start.sh ENTRYPOINT ["start.sh"]
さて、このイメージを使って PDF を作って見ると、PDF はできるにはできるが、UML の図が表示できない。
plantuml-service では SVG で UML をレンダリングしているので、PNG ならどうだろうかと試そうにも plantuml-service は SVG のみサポートなので使えない。PDF 作成時のみローカルで PlantUML を動作するようにして試してみたがダメだった。
イメージを小さくしようと alpine ベースのイメージをベースにしていたが、そのかわり calibre やそれが依存している glibc を自前でビルドするようにしていたらそこに何らかの不足があるようだ。
試しに Debian ベースのイメージをベースに作り直した。それでは calibre もパッケージマネージャでインストールできる。UML を含む PDF の出力も問題なく出力できる。
最終的に gitbook の Dockerfile は次のようになった。
FROM node:10.13.0-slim LABEL maintainer="HeRoMo" # install apt packages RUN apt-get update -y && \ apt-get install -y \ bzip2 \ calibre && \ apt-get autoremove -y && \ apt-get clean && \ rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* RUN yarn global add gitbook-cli svgexport COPY ./start.sh /usr/bin/ RUN chmod 755 /usr/bin/start.sh ENTRYPOINT ["start.sh"]
シンプルになった。イメージのサイズは約 900MB と少々大きくなったけど。
リポジトリは次の通り。
Dockerhub はこちら。