\chapter{LaTeX Docker} \ChapterLabel{LatexDocker} \index{Docker}\index{TeX Live}\index{LaTeX Docker} \section{Purpose and Scope} This chapter records a Docker container that compiles a \LaTeX\ document with \gls{texlive}, the distribution Overleaf uses to compile projects.\footnote{\url{https://www.overleaf.com/learn/latex/Overleaf_and_TeX_Live}} Like Overleaf, it drives pdf\LaTeX\ with \texttt{latexmk}, which reruns the engine until cross-references settle. The container is a command-line compiler. It reads a \texttt{.tex} file from a mounted folder, writes the PDF back to that folder, and exits. It opens no network ports. The image is not deployed to a course host or published to a registry; it was built and tested locally under WSL on Payton's workstation. \section{Design} \begin{tabularx}{\linewidth}{L{3.6cm}Y} \toprule \textbf{Decision} & \textbf{Choice and rationale}\\ \midrule Base image & \texttt{debian:trixie-slim}. Debian packages its TeX Live release, so the image needs no separate TeX Live installer or mirror.\\ TeX Live packages & \texttt{texlive-latex-base}, \texttt{texlive-latex-recommended}, \texttt{texlive-fonts-recommended}, and \texttt{lmodern}, installed without recommended extras. This covers common packages such as \texttt{amsmath}, \texttt{hyperref}, and \texttt{booktabs} while avoiding the multi-gigabyte full distribution.\\ Build driver & \texttt{latexmk} with pdf\LaTeX, nonstop mode, and halt on the first error, so a failed compile returns a nonzero exit status.\\ Interface & The entrypoint is the compiler; the default argument is \texttt{hello.tex}, and any other file name can be passed to \texttt{docker run}.\\ Source and output & The document folder is bind-mounted at \path{/work}, so sources are not baked into the image and the PDF is written to the host.\\ Privilege & The image defaults to an unprivileged \texttt{latex} user; at run time the container uses the invoking user's IDs so output files are owned by that user. The font cache is kept in \path{/tmp}, outside the mounted folder.\\ \bottomrule \end{tabularx} \section{Container Sources} \paragraph{Dockerfile} \inputminted{docker}{docker/latex-compiler/Dockerfile} \paragraph{.dockerignore} The sample folder is mounted at run time, so it is excluded from the build context. \begin{minted}{text} sample *.pdf \end{minted} \paragraph{Sample document: sample/hello.tex} The document exercises T1 fonts, mathematics, a \texttt{booktabs} table, hyperlinks, and a forward equation reference that resolves only on a second pdf\LaTeX\ pass. \inputminted{latex}{docker/latex-compiler/sample/hello.tex} \section{Build and Run} All commands run in a WSL shell from \path{docker/latex-compiler}. \subsection{Build the Image} \begin{minted}{bash} docker build -t ssw590-latex . docker image ls ssw590-latex \end{minted} \subsection{Compile the Sample Document} \begin{minted}{bash} docker run --rm --user "$(id -u):$(id -g)" -v "$PWD/sample:/work" ssw590-latex ls -l sample/hello.pdf grep "Output written" sample/hello.log \end{minted} \texttt{-{}-rm} deletes the container when compilation ends. \texttt{-{}-user} makes the generated files belong to the WSL user instead of the container user. \section{Test Evidence} \begin{figure}[H] \centering \includegraphics[width=\linewidth]{figures/latex-docker-build.png} \caption{TeX Live image build under WSL.} \label{fig:latex-docker-build} \end{figure} \begin{figure}[H] \centering \includegraphics[width=\linewidth]{figures/latex-docker-output.png} \caption{Information about the produced PDF.} \label{fig:latex-docker-output} \end{figure} \begin{figure}[H] \centering \fbox{\includegraphics[width=0.8\linewidth,page=1]{figures/latex-docker-hello.pdf}} \caption{First page of the PDF produced by the container.} \label{fig:latex-docker-hello} \end{figure}