Edited at

AsciiDoc+ブラウザ自動更新環境のDockerイメージを作った


はじめに

Asciidocによるドキュメント作成時のライブプレビュー環境をDockerを使って構築しました。

動機は、Asciidoctorにはライブプレビュー機能(mkdocs servegitbook serveのような機能)が提供されていないので欲しかったからです。

公式サイトにもlive-previewの方法は書いてあるんですが、ChromeかFirefox固定で、更に拡張機能を入れないといけない方法です。

流石にそれは嫌、ということでサーバ側のみで完結する方法を探しました。

ちなみにDockerを使った理由は以下です。


  1. ruby+Node.jsの構成になってしまったので、環境構築を簡単にしたかった


    • 布教しようと考えた時に、非プログラマーの人にこの2つの環境を作れと言えないので。。。dockerならOK?



  2. 遅ればせながら、wsl上でdockerを使えるようになっていることを知ったため。



  3. 公開することを考えてDockerを使ったことがなかったので、使えるようになりたかった




結論

以下を作成して、asciidoctorのライブプレビュー環境を作成



  1. asciidoctor + filewatcher によるasciidoctorの自動ビルドのdockerイメージ dbgso/asciidoctor-watcher


  2. simple-autoreload-server によるブラウザオートリロードのdockerイメージdbgso/autoreloadserver

使い方


  1. 以下のファイルをdocker-compose.ymlとして保存


  2. mkdir dataでマウント用ディレクトリ作成


  3. sudo docker-compose upで起動


  4. sudo chown -R $USERNAME:$USERNAME dataで権限変更。(マウント時にrootの持ち物になってしまうので)


  5. data/index.adocでasciidoctorのファイル作成・更新を行う


  6. http://localhost:18080/index.html を開くとdata/index.adocの変更内容がオートリロードされる


docker-compose.yml

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作成

以下動きをするコンテナをそれぞれ作成した


  1. Asciidoctorによる自動ビルド

  2. 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すれば動きます。


docker-compose.yml

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


こんな感じのものができました。バッチリ作図、コードハイライトも効いています

sample_adoc.png


sample.adoc

: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は別ファイルにしました


sample.puml

@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はフロントマター等のオプションが多い+まとまってない感じがするので、それをまとめる記事を書いたりしようかなと思ってます