はじめに
Asciidocによるドキュメント作成時のライブプレビュー環境をDockerを使って構築しました。
動機は、Asciidoctorにはライブプレビュー機能(mkdocs serve
、gitbook serve
のような機能)が提供されていないので欲しかったからです。
公式サイトにもlive-previewの方法は書いてあるんですが、ChromeかFirefox固定で、更に拡張機能を入れないといけない方法です。
流石にそれは嫌、ということでサーバ側のみで完結する方法を探しました。
ちなみにDockerを使った理由は以下です。
- ruby+Node.jsの構成になってしまったので、環境構築を簡単にしたかった
- 布教しようと考えた時に、非プログラマーの人にこの2つの環境を作れと言えないので。。。dockerならOK?
- 遅ればせながら、wsl上でdockerを使えるようになっていることを知ったため。
- WSL上でDocker Engineが動くようになっていたっぽいという話
- ただ、docker-composeは使えないので今回の記事は意味無いです
- 公開することを考えてDockerを使ったことがなかったので、使えるようになりたかった
- DockerhubのAutomated build を設定する を参考にさせていただきました
結論
以下を作成して、asciidoctorのライブプレビュー環境を作成
-
asciidoctor
+filewatcher
によるasciidoctorの自動ビルドのdockerイメージ dbgso/asciidoctor-watcher -
simple-autoreload-server
によるブラウザオートリロードのdockerイメージdbgso/autoreloadserver
使い方
- 以下のファイルを
docker-compose.yml
として保存 -
mkdir data
でマウント用ディレクトリ作成 -
sudo docker-compose up
で起動 -
sudo chown -R $USERNAME:$USERNAME data
で権限変更。(マウント時にrootの持ち物になってしまうので) -
data/index.adoc
でasciidoctorのファイル作成・更新を行う -
http://localhost:18080/index.html を開くと
data/index.adoc
の変更内容がオートリロードされる
version: '3'
services:
adoc:
image: dbgso/asciidoctor-watcher:0.1
volumes:
- document_root:/data
container_name: adoc_container
working_dir: '/data'
nodeapp:
image: dbgso/autoreloadserver:0.1
volumes:
- document_root:/data
container_name: autoreloadserver
working_dir: '/data'
ports:
- 18080:8080
volumes:
document_root:
driver_opts:
type: none
device: $PWD/data
o: bind
Dockerfile作成
以下動きをするコンテナをそれぞれ作成した
- Asciidoctorによる自動ビルド
- htmlが生成されたタイミングでブラウザをリロード
自動ビルド環境作成
ソースとなるAsciidocファイルが更新された時に自動ビルドを行うDockerイメージを作成しました。
Asciidoctorによるビルド環境自体はdockerhubに公開されているので、これをベースとしてファイル更新の監視機能とコードハイライト機能を追加で組み込みました。
公開されているイメージにはPlantUMLやblockdiag等の環境も用意されているので、テキストで作図もできます。ここの環境も作りたかったので、このDockerイメージをベースにしました。
追加ライブラリ
- ファイル更新の監視
- filewatcher
- コマンドラインレベルで使えるてお手軽だったのと、alpine環境でも追加インストール等いらずで簡単に使えたので(Guardはビルドが中々通らなかった)
- コードハイライト
- coderay
- Ruby製で相性が良さそうだったので(
これしか使ったことがないので)
オートリロード環境
HTMLファイルが変更された時にブラウザをリロードするために、オートリロードsimple-autoreload-serverのライブラリを利用。これを組み込んだDockerイメージを作成しました。
まあやっていることはNode.js
+simple-autoreload-server
というだけの環境なので、このコンテナ単体で使うメリットはあまり無いですね。
別コンテナと連携したくて作った感じです。
docker-composeによる起動
dockerコマンドでもいいですが、docker-composeの方が簡単なのでその方法でいきます。
利用方法
↑でイメージができたので、この2つを連携させた状態で起動します。
最初にも書きましたが、以下のファイルを用意してdocker-compose up
すれば動きます。
version: '3'
services:
adoc:
image: dbgso/asciidoctor-watcher:0.1
volumes:
- document_root:/data
container_name: adoc_container
working_dir: '/data'
nodeapp:
image: dbgso/autoreloadserver:0.1
volumes:
- document_root:/data
container_name: autoreloadserver
working_dir: '/data'
ports:
- 18080:8080
volumes:
document_root:
driver_opts:
type: none
device: $PWD/data
o: bind
↑のファイルを作成したら、以下の手順で起動します。
mkdir data # マウント対象のディレクトリ作成
touch data/index.adoc # ソースとなるファイル作成
docker-compose up # コンテナ起動
sudo chown -R $USERNAME:$USERNAME data # dataディレクトリの権限変更。(マウント時にrootの持ち物になってしまうので)
この状態で、 http://localhost:18080/index.html を開くとindex.adoc
の変更内容が自動的に反映されます。
あとは、index.adocに追記していくなり、ファイルを分割して進めていくなりすれば良いです。
※ dataディレクトリ配下の権限には注意してください。dockerを使っているとルート権限で操作することが多いので、そのまま行くと通常ユーザの時に書き込めくなるので
マウント時にroot以外の権限にする方法無いですか?誰か教えてください
動作概要
、./data
が2つのコンテナにマウントされます。
-
adoc_container
コンテナがindex.adoc
の変更を監視してasciidoctor
コマンドを実行 -
autoreloadserver
コンテナが出力されたindex.html
の変更を監視して、ブラウザをリロードしてくれます
デフォルトではdata/index.adoc
が開始のファイルと定義してあるので、このファイル名のファイルを作成して執筆すれば自動ビルドしてくれます。(読み込むファイルを変更する方法もありますが、今回は省略します)
最小構成の場合のフォルダ構成は以下のような感じです。
./data
./data/index.adoc
./docker-compose.yml
例
こんな感じのものができました。バッチリ作図、コードハイライトも効いています
:toc: left
:source-highlighter: coderay
= サンプル
== はじめに
サンプルファイル
== 作図
* PlantUML
* blockdiag
* 他にも色々いける
=== PlantUML
aiueo
[plantuml, sample, png]
--
include::sample.puml[]
--
=== blockdiag
[blockdiag, blockdiag, png]
--
blockdiag {
// Set span metrix
span_width = 240;
span_height = 120;
adoc -> html, PDF;
}
--
== ハイライト
[source, javascript]
--
class Hoge {
constructor() {
this.num = 1;
}
}
--
ファイル分割もできるので、plantumlは別ファイルにしました
@startuml hoge
actor user as user
participant filewatcher
collections "asciidoc files" as adoc
participant autoreloadserver
collections html as html
par 監視
filewatcher -> adoc: 監視
activate filewatcher
else
autoreloadserver -> html: 監視
activate autoreloadserver
end
...
== オートビルド ==
user -> adoc: ファイル保存
activate adoc
adoc -> filewatcher: ファイル変更検知
deactivate adoc
activate filewatcher
filewatcher -> html : build
html --> filewatcher: ok
deactivate filewatcher
== ブラウザオートリロード ==
activate html
html --> autoreloadserver: ファイル変更検知
autoreloadserver -> user: WebSocket ブラウザリロード
@enduml
おわりに
Asciidoctorの執筆環境をDockerを使って構築しました。
AsciidoctorはMarkdownと同程度の書きやすさで表現力が高いので、もっと流行ってほしいです。ただ、環境構築は多少ネックになるのかなと思うので今回作ったイメージで多少楽できて、布教できたら良いなと思います。
あと、asciidoctorはフロントマター等のオプションが多い+まとまってない感じがするので、それをまとめる記事を書いたりしようかなと思ってます