📖

グローバル環境を可能な限り汚染せずにMarkdownから組版のPDFを生成(ゆめみ大技林 '23)

2023/05/26に公開

本稿は2023年5月に開催された技術書典 14技術書同人誌博覧会 8にて無料で配布していた ゆめみ大技林 '23の寄稿している記事のウェブ版です。

グローバル環境を可能な限り汚染せずにMarkdownから組版のPDFを生成

組版の PDF を生成するためのツールに Vivliostyle があります。本書籍も Vivliostyle を使用して Markdown ファイルから組版の PDF を生成していますが、各々の環境で Vivliostyle をどうやって動かすかという課題がありました。当初は yarn を使って Vivliostyle をインストールしていました。そこで問題となるのが PATH や各端末にインストールされているツールのバージョンの違いなど、環境要因で環境構築に失敗するケースがあります。

そこで本稿では環境依存の問題を極力発生しない形で Vivliostyle を動かす方法をご紹介します。

本稿で紹介すること

  • Vivliostyle を使用して Markdown ファイルから組版の PDF を生成する方法
  • Vivliostyle を動かす時に可能な限り依存ツールをインストールしない方法(本稿ではそれをグローバル環境を汚染しないという表現を用いています)
  • make コマンドを活用して、各ツールのインストールと実行を簡略化する方法

動作確認環境

  • OS: macOS 13.3.1 (a) (22E772610a)
  • CPU: Apple M2 Pro

本稿のサンプルコード

本稿のサンプルコードは https://github.com/yusuga/markdown-to-typesetting-pdf になります。

本稿で取り扱うツール

ツール名 用途
brew macOS向けのパッケージマネージャー
Docker コンテナ仮想化プラットフォーム
colima Dockerコンテナを実行するための軽量なLinuxベースの仮想化環境
Vivliostyle Web技術を用いて電子書籍の作成、表示、印刷を可能にするCSSフレームワーク

Markdownから組版のPDFを生成する方法

1. brewをインストール

brew は macOS のパッケージマネージャーです。いわば、ツールを管理するためのツールです。

まず、brew 自体は次のようにインストールします。執筆時点で公式サイトに記載のもののため、今後変更される可能性があることにご注意ください。

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/
install.sh)"

2. Dockerをインストール

Docker は、コンテナ型の仮想環境を実行するためのプラットフォームです。

仮想環境とは、macOS 上に別の OS を仮想的に構築して、その仮想環境内に閉じた形で色々なアプリケーションを実行できるというイメージです。

インストール方法は、公式の「Install Docker Desktop on Mac」にインストーラがありますが、本稿では brew 経由でインストールします。

brew install docker

3. colimaをインストール

colima は、Docker コンテナを実行するための軽量な Linux ベースの仮想化環境です。

Docker Desktop は大企業(従業員が 250 人以上、または年間収益が 1,000 万ドル以上)が商用利用する場合には有料のサブスクリプションが必要になります。ただし、 Docker 自体の使用は無料なため、本稿では Dcoker Desktop の代替で colima を利用する方法をご紹介します。

colima は brew 経由でインストールします。

brew install colima

4. colimaの起動

Docker を動かすために colima を起動します。

colima start

5. Vivliostyleの実行

Vivliostyle は、Web 技術を用いて電子書籍の作成、表示、印刷を可能にする CSS フレームワークです。

Vivliostyle は Docker 経由で実行します。PDF を生成するには各種ファイルが必要となるため、現時点ではひとまず -v でバージョンを表示して実行可能なことを確認します。

docker run \
  --rm \
  -v $(pwd):/local \
  -w /local \
  ghcr.io/vivliostyle/cli:6.1.0 -v

Tips

Vivliostyle の Docker image は公式が配布しています。

makeコマンドをタスクランナーとして使用する

ここまでで各ツールのインストールと実行をご紹介しました。本項では、これらのコマンドを make コマンドにまとめて、環境構築も合わせて実行する方法をご紹介します。

makeコマンドとは

make コマンドは、UNIX 系の OS ではデフォルトで使用可能なコマンドです。本来は C で書かれたソースコード一式をビルドするためなどに使われていました。本稿では make コマンドをタスクランナー(各コマンドを実行)として使用します。その他の選択肢としてはシェルスクリプトを使用する方法もあります。筆者は両方運用してみた結果、make コマンドの記述の方がわかりやすいという理由で make コマンドを選択しています。

Makefileの記述

全文は、 yusuga/markdown-to-typesetting-pdf/blob/main/Makefile をご参照ください。

1. 変数を定義

Makefile 内ではさまざまな PATH にアクセスしているため、それらを変数で定義しています。変数名を大文字にしてるのは Makefile の慣例です。定義した変数は $(変数) で展開でき、定義した値が文字列として差し代わるだけの単純な仕組みです。

# Makefileがあるディレクトリを取得するScript
MAKEFILE_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

# 以下は MAKEFILE_DIR から各ディレクトリやファイルへのPATH
MAKEFILE_PATH := $(MAKEFILE_DIR)/Makefile
BOOK_DIR := $(MAKEFILE_DIR)/book
VIVLIOSTYLE_WORKSPACE_DIR := $(BOOK_DIR)/.vivliostyle
OUTPUT_DIR := $(BOOK_DIR)/output
BOOK_PATH := $(OUTPUT_DIR)/ebook.pdf

2. .PHONYを定義

make コマンドは実行時に make コマンド名と同名のファイルやディレクトリがあるとそれらを優先して解釈されます。そこで .PHONY を定義することで make コマンドの実行が優先されるようになります。定義場所はどこでもいいのですが、コマンド定義の前の行に書かれることが多いです。

.PHONY: open
## pdfを開く
open:
	open $(BOOK_PATH)

3. 各ツールのインストール

各ツールを実行する前に必要なツールがインストールされているかを command で確認します。brew のみ、単純にインストールできないためインストールされているかの確認のみになります。

.PHONY: check_brew
check_brew:
	@if ! command -v brew >/dev/null 2>&1; then \
		echo "brewをインストールする必要があります。 https://brew.sh/index_ja"; \
		exit 1; \
	fi

.PHONY: install_docker
install_docker:
	@if ! command -v colima >/dev/null 2>&1; then \
		brew install docker; \
	fi

.PHONY: install_colima
install_colima:
	@if ! command -v colima >/dev/null 2>&1; then \
		brew install colima; \
	fi

.PHONY: start_colima
start_colima:
	@if [ $$(colima status 2>&1 | grep -c "not running") -eq 1 ]; then \
		colima start; \
	fi

複数の make コマンドを 1 つの make コマンドにまとめます。make コマンドは次のようにコマンド名をスペース区切りで記述すると順番に実行されます。

.PHONY: prepare_docker
prepare_docker: \
  check_brew \
  install_docker \
  install_colima \
  start_colima

4. Dockerの実行

Docker の実行の前に前述の prepare_docker を実行させるために DOCKER 変数を定義します。これにより $(DOCKER) run と書けば、必ず prepare_docker を実行してから docker run を実行できます。

DOCKER = \
  @$(MAKE) prepare_docker; \
  $(shell command -v docker)

Tips

変数への代入は := ではなくて = を使用します。これらは変数の初期化タイミングの違いがあります。:= は即時展開変数といい、変数に値を代入するタイミングで式が評価されます(実行されます)。= は単純展開変数といい、変数が参照されたタイミングで式が評価されます。これらは変数にコマンドを書く場合には注意する必要があり := で書いてしまうと、make コマンドの実行前に変数が確定してしまうため(つまりは式が評価される)、= を使う必要があります。

5. Vivliostyleの実行

Docker 経由での Vivliostyle の実行には前述の DOCKER 変数を使用します。こうすることで Vivliostyle を実行するために必要なツールのインストールと Docker を実行可能な状態にできます。本稿では Vivliostyle で build するために必要なことは割愛しますが、サンプルコードには build するために最低限必要なファイルが追加してあります。

## https://github.com/vivliostyle/vivliostyle-cli/pkgs/container/cli
VIVLIOSTYLE_CLI_IMAGE_NAME := ghcr.io/vivliostyle/cli
VIVLIOSTYLE_CLI_IMAGE_TAG := 6.1.0

VIVLIOSTYLE_CLI = $(DOCKER) run \
  --rm \
  -v $(BOOK_DIR):/local \
  -w /local \
  $(VIVLIOSTYLE_CLI_IMAGE_NAME):$(VIVLIOSTYLE_CLI_IMAGE_TAG)

.PHONY: pdf
## pdfを生成
pdf:
	$(VIVLIOSTYLE_CLI) build \
		--no-sandbox

Tips

Docker image 名とタグバージョンを変数化することで、バージョンの変更をしやすくしています。

6. 生成ファイルの削除

環境構築時に生成した各種ファイルや生成した成果物を削除する make コマンドです。何か問題が発生し、リセットしたい場合に役立ちます。

.PHONY: clean
## 生成ファイルをすべて削除
clean:
	rm -rf $(VIVLIOSTYLE_WORKSPACE_DIR)
	rm -rf $(OUTPUT_DIR)
	@if command -v colima >/dev/null 2>&1; then \
		$(MAKE) stop_colima; \
	fi

Tips

make コマンドでは環境構築のリセットや生成物の削除する用途のコマンドには、慣例的に clean が命名されています。

まとめ

本稿では、Docker を使うことによって Vivliostyle を動かすために必要なツールをグローバルな環境にインストールせず実行する方法をご紹介しました。また、Docker Desktop の代わりに colima を利用することで、Docker を無料で使用できるため、どなたでも気軽に試せる構成になっています。

前回のゆめみ大技林 '22 では「グローバル環境を汚染しない Xcode の開発環境構築」を執筆したのですが、今回も同様に Docker を利用して環境依存の問題をなくそうというテーマでした。最近は Ruby や Node を使わないといけないなったらすぐに Docker を使って環境を分離したい、という思考になってきています。さまざまなツールにより便利になっていく反面、より環境構築周りが複雑化してきている気がします。引き続き環境依存をなくしたツール利用を模索していきたいです。

株式会社ゆめみ

Discussion