TeX Live 入りコンテナと Makefile で LaTeX 文書をコンパイルする

はじめに

LaTeX 文書のコンパイルには TeX Live などのディストリビューションが必要ですが、ローカルに数 GB のフルインストールを行うと、マシンごとにバージョンが揺れたり、数年後に再ビルドできなくなったりします。TeX Live 入りの Docker コンテナを用意しておけば、環境はイメージの中に固定され、どのマシンでも、CI 上でも同じ PDF が得られます。

とはいえ docker run に長いオプションを毎回打つのは現実的ではありません。そこで Makefile にコンテナの起動と latexmk の呼び出しをまとめ、make だけでコンパイルできるようにします。この記事ではその最小構成を示します。

全体像

プロジェクト/
├── Dockerfile        … TeX Live 入りイメージの定義(任意。公式イメージ直利用も可)
├── Makefile          … コンテナ起動と latexmk 呼び出しをまとめる
├── .latexmkrc        … 組版エンジンとビルド経路の指定
└── main.tex          … 原稿

make を実行すると、Makefile がコンテナを起動し、その中で latexmk main.tex が走り、ホスト側に main.pdf が出力されます。

コンテナを用意する

公式イメージをそのまま使う

もっとも手軽なのは Docker Hub の texlive/texlive です。latexmk や和文パッケージ(collection-langjapanese)を含むフル構成で、latest のほか TL2024 のような年号入りタグがあります。年号タグを指定すると、その年の TeX Live に固定でき再現性が上がります。

docker pull texlive/texlive:TL2024

Dockerfile で薄く作る

イメージサイズを抑えたい、あるいは特定のパッケージやフォントを足したいときは、公式イメージをベースに Dockerfile を書きます。

# TeX Live を年号で固定。必要なものだけ追加する
FROM texlive/texlive:TL2024

# 例:latexmk・和文一式・推奨フォントを明示的に導入
RUN tlmgr install \
      latexmk \
      collection-langjapanese \
      collection-fontsrecommended \
 && tlmgr path add

WORKDIR /work
docker build -t mytex:latest .

いずれの場合も、コンテナはコンパイルのたびに使い捨て(--rm)にし、原稿ディレクトリだけをボリュームでマウントする方針にします。

docker run を手で叩くと

Makefile にまとめる前に、素の起動コマンドを確認しておきます。

docker run --rm \
  -v "$PWD":/work -w /work \
  -u "$(id -u):$(id -g)" -e HOME=/tmp \
  mytex:latest \
  latexmk main.tex

ポイントは 3 つです。

  • -v "$PWD":/work -w /work … カレントディレクトリをコンテナ内 /work にマウントし、そこを作業ディレクトリにする。生成された PDF はホスト側にそのまま残る。
  • -u "$(id -u):$(id -g)" … コンテナ内のプロセスをホストと同じ UID/GID で動かし、出力ファイルが root 所有になるのを防ぐ。
  • -e HOME=/tmp … 上記で HOME が無いユーザーになるため、latexmk や tlmgr が書き込み先に困らないよう書き込み可能な HOME を与える。

Makefile にまとめる

この起動処理を変数 RUN に押し込み、各ターゲットから使い回します。

# ==== 設定(コマンドラインから上書き可)====
IMAGE  ?= mytex:latest      # 使うイメージ
DOC    ?= main              # 対象は $(DOC).tex
DOCKER ?= docker

# コンテナ内でコマンドを1回実行するための共通部分
RUN = $(DOCKER) run --rm \
	-v "$(CURDIR)":/work -w /work \
	-u "$(shell id -u):$(shell id -g)" -e HOME=/tmp \
	$(IMAGE)

.PHONY: all image build watch shell clean distclean help

all: build

## image   : Dockerfile からイメージをビルド(初回・Dockerfile 変更時のみ)
image:
	$(DOCKER) build -t $(IMAGE) .

## build   : コンテナ内で latexmk を1回まわして PDF を生成
build:
	$(RUN) latexmk $(DOC).tex

## watch   : 保存のたびに自動で再コンパイル(Ctrl-C で終了)
watch:
	$(RUN) latexmk -pvc -view=none $(DOC).tex

## shell   : コンテナの中に入って手作業する
shell:
	$(DOCKER) run --rm -it -v "$(CURDIR)":/work -w /work $(IMAGE) bash

## clean   : 中間ファイルを削除(PDF は残す)
clean:
	$(RUN) latexmk -c $(DOC).tex

## distclean: PDF も含めて生成物を全部削除
distclean:
	$(RUN) latexmk -C $(DOC).tex

## help    : ターゲット一覧を表示
help:
	@grep -E '^## ' $(MAKEFILE_LIST) | sed 's/^## //'

Makefile のレシピ行は、行頭がスペースではなくタブでなければなりません。コピー時に崩れたら make が missing separator を出します。

使い方は次のとおりです。

make image     # 最初に一度(公式イメージを直接使うなら不要)
make           # main.pdf を生成
make watch     # 執筆中は監視モード
make clean     # 中間ファイルの掃除

DOC や IMAGE はコマンドラインで上書きできます。

make build DOC=chapter1
make build IMAGE=texlive/texlive:TL2024

.latexmkrc(和文文書の場合)

和文は upLaTeX で DVI を作り dvipdfmx で PDF 化する経路が一般的です。コンテナ内にはビューアがないので、プレビュー系は無効にしておきます。

$latex        = 'uplatex %O -synctex=1 -halt-on-error -interaction=nonstopmode %S';
$bibtex       = 'upbibtex %O %B';
$biber        = 'biber %O --bblencoding=utf8 -u -U --output_safechars %B';
$makeindex    = 'upmendex %O -o %D %S';
$dvipdf       = 'dvipdfmx %O -o %D %S';
$pdf_mode     = 3;     # DVI -> PDF
$max_repeat   = 5;
$view         = 'none';

このファイルをリポジトリに含めておけば、make する人・CI のどちらも同じ設定で組版できます。詳しくは latexmk の記事を参照してください。

CI へそのまま持ち込む

ローカルで使っているイメージを CI でも指定すれば、手元と同じ環境でビルドできます。GitLab CI の例:

compile:
  image: texlive/texlive:TL2024
  script:
    - latexmk main.tex
  artifacts:
    paths:
      - main.pdf

GitHub Actions なら container: に同じイメージを指定します。CI 側では Docker を介さず直接 latexmk を呼べるので、Makefile の build ターゲットの中身(latexmk $(DOC).tex)だけをそのまま流用できます。「ローカルは make、CI はイメージ直実行、コマンドは同一」という形に落ち着きます(詳しくは GitHub Actions で自動化する)。

関連記事

まとめ

  • TeX Live 入りコンテナを使うと、組版環境をイメージに固定でき、マシン差や経年劣化に強くなる。年号タグでの固定が要点。
  • docker run の定型オプション(マウント、UID 合わせ、HOME)を Makefile の共通変数にまとめると、make だけでコンパイルできる。
  • .latexmkrc と同じイメージを CI にも渡せば、ローカルと CI で同一の PDF が得られる。

原稿と一緒に Dockerfile / Makefile / .latexmkrc を配布する運用にしておくと、受け渡し先でも「make するだけ」で再現できます。

LaTeX組版・教材校正のご依頼・ご相談はコレクトコネクトへお問い合わせください。

← コラム一覧へ