TL;DR
- LaTeX を書きたいけど、ローカルに TeX Live を入れるのは重いしバージョンも汚したくない。
- かといって Overleaf(クラウド)だと手元の Git 管理と噛み合わない。
- そこで 「TeX Live は Docker に閉じ込め、原稿
.texの 1 行目に自己ビルド行を仕込む」 ことで、次のように原稿ファイル自身を実行するだけでビルドできる環境を作る。
sh paper.tex # ← これだけで Docker 内の TeX Live が走り、PDF が出る
ホストに必要なのは Docker だけ。TeX Live も latexmk もインストール不要。生成物は全部サブディレクトリに隔離され、そのまま Git 管理からも外れる。この記事はその作り方と、なぜ動くのかの解説です。
完成形
ディレクトリはこうなります。
paper.tex ← 原稿(これを sh で実行する)
paper/ ← 出力先 兼 素材置き場
├── paper.pdf ← 生成された PDF
├── paper.aux / .log / ... ← 中間生成物(全部ここ)
├── refs.bib ← 参考文献(原資産)
└── fig01.png ← 図(原資産)
paper/.gitignore ← 中間生成物を Git 管理外にする
paper.tex の中身(重要なのは 1 行目):
% 2>/dev/null; MSYS_NO_PATHCONV=1 exec docker run --rm -v .:/work -w /work texlive/texlive:latest latexmk -pdf -interaction=nonstopmode -outdir="${0%.tex}" "$0"
\documentclass{article}
\usepackage{graphicx}
\begin{document}
Hello, \LaTeX! \includegraphics[width=3cm]{fig01.png}
\end{document}
そして sh paper.tex を実行すると、Docker 内の TeX Live で latexmk が走り、paper/paper.pdf が生成されます。
なぜ動くのか
肝は 3 つです。
1. .tex を「TeX と shell の両方で有効なファイル(polyglot)」にする
TeX のコメントは %、shell のコメントは #。これを利用します。
% 2>/dev/null; MSYS_NO_PATHCONV=1 exec docker run ... latexmk ... "$0"
-
TeX から見ると: 先頭が
%なので行まるごとコメント。PDF には一切影響しない。 -
shell から見ると(
sh paper.texで起動):%はジョブ制御として誤読されるが、そのエラーを2>/dev/nullで捨て、続くexec docker run ...を実行。execで shell 自身を Docker プロセスに置き換えるので、以降の TeX コードは shell に読まれない。
⚠️ 本物の shebang (
#!/bin/sh) を 1 行目に置くのは NG です。TeX は#を「マクロ引数文字」と解釈してエラーになります。だから%始まりにして、sh paper.texと明示的に呼ぶ形にしています。
$0 は実行中のファイル名(= paper.tex)。${0%.tex} はそこから .tex を除いた文字列(= paper)で、これを -outdir に渡します。
2. -outdir の「二重利用」がクリーンさの本質
latexmk -outdir="${0%.tex}" は、出力先を paper/ に指定します。これで:
-
生成物(PDF・aux・log 等)が全部
paper/に集まる → 原稿の横が汚れない - そして地味に効くのが、TeX Live では
-outdir(=-output-directory)が入力ファイルの探索先も兼ねるという挙動。つまりpaper/に置いた.sty/.bst/.bib/ 画像が、パス無しで参照できる。
\includegraphics{fig01.png} % paper/fig01.png が見つかる
\bibliography{refs} % paper/refs.bib が見つかる
\usepackage{cvpr} % paper/cvpr.sty が見つかる
出力先と素材置き場を同じ paper/ にしたことで、「生成物の隔離」と「素材のパス無し参照」が1 つの選択から芋づる式に得られます。
3. TeX Live を Docker に閉じ込める
texlive/texlive:latest(scheme-full、約 5GB)を使えば、pdfLaTeX / XeLaTeX / LuaLaTeX / latexmk / bibtex / 各種パッケージが全部入っています。ホストには何も入れません。
docker pull texlive/texlive:latest # 初回のみ
docker run のオプションの意味:
| 部分 | 意味 |
|---|---|
--rm |
コンテナを使い捨て |
-v .:/work |
カレントディレクトリをコンテナ内 /work にマウント |
-w /work |
作業ディレクトリを /work に(相対パスがここ基準で解決) |
latexmk -pdf ... |
コンテナ内で実行する実コマンド |
.gitignore で生成物を Git から外す
paper/ には生成物と原資産が同居するので、拡張子ベースで生成物だけ無視します(paper/.gitignore)。
# latexmk の生成物を Git 管理外に。図(*.png)・*.sty・*.bib 等の原資産は追跡される。
*.aux
*.fdb_latexmk
*.fls
*.log
*.out
*.pdf
*.synctex.gz
*.toc
*.bbl
*.blg
.bib や .png は無視対象に入れていないので、参考文献や図はちゃんと Git 追跡されます。
応用が効く
BibTeX(引用)
paper/refs.bib を置いて \cite を書くだけ。latexmk が bibtex を自動で回して引用を解決します。
See prior work~\cite{sample2024}.
\bibliographystyle{plain}
\bibliography{refs}
学会スタイル(CVPR など)をそのまま適用
配布された cvpr.sty / .bst 一式を paper/ に放り込み、.tex で \usepackage{cvpr} するだけ。前述の「-outdir が入力探索先も兼ねる」おかげで、パス無しで解決します。
日本語論文(LuaLaTeX)
\documentclass{article} + pdfLaTeX は、組版される日本語で Unicode character エラーになります。日本語で書くなら、自己ビルド行を -lualatex に、クラスを ltjsarticle(luatexja)にします。
% 2>/dev/null; MSYS_NO_PATHCONV=1 exec docker run --rm -v .:/work -w /work texlive/texlive:latest latexmk -lualatex -interaction=nonstopmode -outdir="${0%.tex}" "$0"
\documentclass{ltjsarticle} % 日本語本文をそのまま組める
\begin{document}
これは日本語の本文です。数式 $E=mc^2$ も使えます。
\end{document}
inputenc/fontenc は不要(LuaLaTeX はネイティブ UTF-8)。これで sh paper.tex だけで日本語 PDF が出ます。
注意点・限界
-
shell が要る:
sh paper.texで起動する前提。Windows なら Git Bash / WSL で。 -
MSYS_NO_PATHCONV=1は Git Bash のパス自動変換(/workが Windows パスに化ける)を抑止するために自己ビルド行へ埋め込み済み。ユーザーが打つ必要はありません。WSL / Linux / macOS では無害です。 -
chmod +xして./paper.tex直起動は不可(本物の shebang が使えないため)。必ずsh paper.tex。 -
原稿のあるディレクトリで実行すること(
\includegraphicsも-outdirも cwd 基準で解決するため)。 - 初回だけイメージ取得に時間がかかる(約 5GB)。以後はローカルにキャッシュされます。
まとめ
-
原稿
.texの 1 行目に自己ビルド行を仕込むことで、sh paper.texだけでビルドできる。 - TeX Live は Docker に閉じ込めるので、ホストは Docker だけあればよい(環境を汚さない・再現性が高い)。
-
-outdirを素材置き場と共用することで、生成物の隔離と「sty/bst/bib/画像のパス無し参照」が同時に手に入る。 - BibTeX・学会スタイル・日本語(LuaLaTeX)まで、同じ仕組みで拡張できる。
「Overleaf の"開けば動く"を、ローカル・Git 管理下で再現する」小さな仕掛けです。TeX 環境構築でつまずいた経験がある人ほど、刺さると思います。