36
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

モダンなLaTexで書いたレポートを簡単にdockerでPDFに変換してCIで配布する方法

Last updated at Posted at 2018-08-23

output.gif

TL;DR

dockerがインストールされているPCで

docker pull eisoku9618/latex:latex-japanese
cd /path/to/target_dir
docker run --rm -it --user=`id -u $USER` -w=/root -v $(pwd):/root eisoku9618/latex:latex-japanese /bin/bash -c "latexmk -pvc main.tex"
evince /path/to/target_dir/.tmp/main.pdf

をすると,上のgifのように生成されるPDFを見ながらソースとなるtexを編集することが出来る.
そして,texファイルが完成したら,
PDFはコミットせずtexファイルのみをgitlabにコミットすることで,
gitlab-ciが回って,上記と同じ手順で最新のtexファイルをPDFに変換し,それをブラウザで見れるようにしてくれる.
例えば, https://gitlab.com/eisoku9618/report のREADME.mdから以下のようにPDFを閲覧できる.
image.png

特徴のまとめ

2019/11/24追記: notoフォントを使うとdocker imageが大きくなるので,より軽いかつ日本語なipaexフォントを使うようにした.

ポイント 参考サイト
日本語フォントにNotoフォントを使う Google Noto Fonts
日本語フォントが埋め込まれたPDFを生成する upLaTeX文書で源ノ明朝/Noto Serif CJKを簡単に使う方法(最新のdvipdfmxとpxchfonを使用)
texを更新する度にPDFを自動で再生成する 数式ありのレポートや本をモダンに書く
必要な環境はdockerで構築してポータブルにする DockerhubのAutomated buildを試す
texファイルのみをgit管理下において,PDFはブラウザから閲覧できるようにする Introduction to job artifacts

設定手順

ここでは,上記を実現するための手順を備忘録として書いておく.

STEP0: 日本語フォントにNotoフォントを使う

texで簡単に使える日本語フォントとしては,デフォルト(texlive-lang-japanese)でインストールされるIPAフォントまたはIPAexフォントがあるが,IPA/IPAexを埋め込んだPDFをブラウザで閲覧すると日本語が表示されないことがある.
詳細は分かっていないがpdffonts hoge.pdfしたときにuniの列がNoになっている場合はそうなるらしい.

そこで,notoフォントをインストール(aptで入る)して,それを埋め込むと,pdffontsの結果が次のようになって,uniの列がYesになって,ブラウザから見た時にも日本語が表示されるようになる!
STEP4でPDFをブラウザで閲覧できるようになるので,IPAフォントではなくてnotoフォントを使うことにする.
※ フォント自体にこだわりはなくて,インストールが簡単,かつ,uniYesになるフォントであれば何でも良い

pdffontsの結果
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
QYAGJC+NotoSerifCJKjp-Regular-Identity-H CID Type 0C       Identity-H       yes yes yes      5  0

STEP1: 日本語フォントが埋め込まれたPDFを生成する

upLaTeX文書で源ノ明朝/Noto Serif CJKを簡単に使う方法(最新のdvipdfmxとpxchfonを使用)で詳しく説明されているように,TeX Live 2017からdvipdfmxが新しくなり,noto/ipaexフォントを埋め込むまでの手順が簡単になった.

例えばUbuntu 16.04だとTex Liveは2015なのでNGで,
Ubuntu 18.04だと2017になってOK.
よって,Ubuntu 18.04にて次のコマンドでuplatexとnotoフォントをインストールすればOK.
また,aptで入れるだけでnoto/ipaexフォントが「TeXから見える状態」になっているので簡単.

(STEP3でDockerにするので次のパッケージを手元でインストールする必要はない)
sudo apt install texlive-lang-japanese # (u)platexをインストールする
sudo apt install fonts-noto-cjk fonts-noto-cjk-extra # noto fontをインストールする
sudo apt install fonts-ipaexfont-gothic fonts-ipaexfont-mincho # ipaex fontをインストールする

STEP2: texを更新する度にPDFを自動で再生成する

texをPDFにするには

  • uplatex main.tex
  • dvipdfmx main.dvi

のようにコマンドを複数回打つ必要がある.
さらに,citerefがあると打つ必要があるコマンドが増えていく.

これでは大変なので,Makefileを自分で作って簡略化する方法があるが,
よりモダンにするにはlatexmkというプログラムを使うのが良いっぽい.
詳しくは数式ありのレポートや本をモダンに書くに書いてある.

  • latexmkaptでインストールできる.

STEP3: 必要な環境はdockerで構築してポータブルにする

STEP0からSTEP2までの内容を手元のPCでやるには大変(dvipdfmxが新しい必要があってUbuntuなら18.04が必要,手元のPCの環境が汚れる,他の人のPCでやるときに0から設定するのは面倒,,,)なので,Dockerで環境構築をして,手元のtexファイルをそのDockerコンテナにマウントしつつ,PDFを生成するのがモダン.

Dockerfile
FROM ubuntu:18.04

ENV DEBIAN_FRONTEND noninteractive

RUN apt update && apt install -y --no-install-recommends \
# for (u)platex
texlive-lang-japanese \
# for CTAN packages
texlive-plain-generic texlive-latex-base texlive-latex-extra \
# for latexmk
latexmk \
# for noto font: Bold and Regular
fonts-noto-cjk \
# for noto font: Black, DemiLight, Light, Medium, Thin and so on
fonts-noto-cjk-extra \
&& rm -rf /var/lib/apt/lists/*

CMD ["/bin/bash"]

確認のために

docker build -t test_container ./
docker run --rm -it test_container /bin/bash

してDockerコンテナに入って

  • kpsewhich NotoSerifCJK-Black.ttc : Notフォントが認識されていることが分かる
  • kanji-config-updmap status: デフォルトのフォントを変更していないことが分かる(CURRENT family for ja: noEmbed
    • notoフォントはtexファイルにて\usepackage[noto-otc, unicode]{pxchfon}とすることで使用するため.

image.png

とすると確認できるし,

/tmp/test.tex
\documentclass[uplatex]{jsarticle}
\usepackage[ipaex, unicode]{pxchfon}

\begin{document}
ハローワールド.
\end{document}

というtexファイルを手下に作り

docker run --rm -it --user=`id -u $USER` -w=/root -v /tmp:/root test_container /bin/bash
uplatex test.tex
dvipdfmx test.dvi

のように手元のPCの"/tmp"をコンテナにマウントして,uplatexdvipdfmxを行うと,
手元のPCに"/tmp/test.pdf"が生成される.
image.png

また,

/tmp/.latexmkrc
#!/usr/bin/env perl
$latex            = 'uplatex -halt-on-error -file-line-error %O %S';
$out_dir          = '.tmp';
$bibtex           = 'upbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'upmendex %O -o %D %S';
$max_repeat       = 5;
$pdf_mode	  = 3; # generates pdf via dvipdfmx

# Prevent latexmk from removing PDF after typeset.
# This enables Skim to chase the update in PDF automatically.
$pvc_view_file_via_temporary = 0;

$view	    = 'none';

のようなlatexmkの設定ファイルを手元の"/tmp"に作り,

docker run --rm -it --user=`id -u $USER` -w=/root -v /tmp:/root test_container /bin/bash -c "latexmk -pvc test.tex"

すると,texが更新される度に/tmp/.tmp/test.pdfも更新されるようになる.
output.gif

また,上記のDockerイメージをdockerhubに置いたものがeisoku9618/latexになるので,

docker pull eisoku9618/latex:latex-japanese

とすればSTEP0から3で構築した環境をコマンド1つで構築することが出来る.

  • Ubuntu 16.04でもTex Live 2017を使える
  • 手元のPCの環境は汚れない
  • 他の人のPCでもすぐに環境構築できる

STEP4: texファイルのみをgit管理下において,PDFはブラウザから閲覧できるようにする

https://gitlab.com/eisoku9618/report に具体例を置いた.

このレポジトリにはバイナリである.pdfはコミットしていないが,
gtilab-ciの設定を次のようにすることでコミットされた.texをPDFにして所定の場所に置いてくれる.

.gitlab-ci.yml
services:
  - docker:dind

latex_job:
  image: eisoku9618/latex:latex-japanese
  script:
    - (for dir in *; do [ -d "${dir}" ] && echo "$dir start" && (cd $dir && latexmk main.tex && mv .tmp/main.pdf ../${dir}.pdf); done)
  artifacts:
    expire_in: 2 days
    paths:
      - ./*.pdf

その所定の場所はREADME.mdに書かれており,以下のようにPDFをブラウザから閲覧できるようになる.
image.png

gitlab-ciの成果物は一定期間経過すると消されてしまうらしいが,
次のように毎日4時にorigin/masterでCIを走らせるようにすることで,
常に最新のPDFを閲覧できるようにすることができる.

image.png

36
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?