
Update on November 1, 2026
Eleven years later I still compile LaTeX this way. Today I rebuilt soleo/docker-latex because I moved my résumé to LaTeX, and it needs XeLaTeX, which the old image's build script never ran. Here is what changed.
| 2015–2016 | 2026 | |
|---|---|---|
| Base image | blang/latex, then ubuntu:xenial (later ubuntu:latest) | Ubuntu 26.04 LTS, pinned |
| TeX | whatever the base shipped | texlive-full, TeX Live 2025 |
| Build | a script that ran pdflatex twice | latexmk, which reruns until references settle |
| Engines | pdfLaTeX | pdfLaTeX, XeLaTeX, LuaLaTeX |
| Image | soleo/latex on Docker Hub | ghcr.io/soleo/latex on GitHub Container Registry |
| Docker on macOS | VirtualBox + docker-machine | Rancher Desktop |
- Pinned base. The image had drifted to
ubuntu:latest, so the TeX Live version changed under me without notice. It now pins Ubuntu 26.04 LTS, so a build today and a build next year use the same TeX Live. - latexmk instead of my build script. The old entrypoint ran
exec pdflatextwice, andexecreplaces the shell, so the second pass and the cleanup never ran. latexmk reruns the engine and BibTeX or biber as many times as references need, then removes the aux files. - XeLaTeX and fonts.
-e LATEX_ENGINE=xelatex(orlualatex) switches the engine. TeX Live's OpenType and TrueType fonts are registered with fontconfig, so a CV template can load Open Sans or Merriweather by name. The repository has an example CV. - Any tool, directly. A command name as the first argument runs as is, for example
biber paperorfc-list :family. - One warning. latexmk runs any
latexmkrcin the folder you mount, and that file is Perl code. Only compile projects you trust.
The commands today. Pull once, then compile with pdfLaTeX, the default:
docker pull ghcr.io/soleo/latex
docker run --rm -v "$PWD":/mnt/src ghcr.io/soleo/latex paper.tex
For a CV or anything with custom fonts, use XeLaTeX:
docker run --rm -v "$PWD":/mnt/src -e LATEX_ENGINE=xelatex ghcr.io/soleo/latex cv.tex
And the shortcut, updated for the new image:
docker-latex() { docker run --rm -v "$PWD":/mnt/src ghcr.io/soleo/latex "$@"; }
The image is big, about 8.2 GB, because texlive-full is everything. That is still the trade I want:
one pull, and no template ever fails on a missing package.
What it builds now is my résumé. The source is a single-column XeLaTeX file in this site's repository, and a GitHub Actions workflow builds it with this image and publishes the PDF behind the résumé page. The PDF's timestamp is the source's last commit time, so the same source always produces the same file, and a workflow run only proposes a change when the résumé actually changed.
The original post (2015)
LaTeX on Dokcer
Update on December 11, 2016:
I'm no longer using the image based on blang/latex, instead it is now based on ubuntu:xenial.
A shortcut bash function I used to for compiling .tex now which is way more easier than before.
docker-latex() { docker run -v $PWD:/mnt/src --rm soleo/latex:latest $@; return $?; }Recently I
just got a my MacBook Pro because my old one died accidentally. That was a story involved with ice
coffee and soda. But that's not important. So after I used my dotfiles
repository(https://github.com/soleo/dotfiles) to set up
everything I need and want to start compiling some old .tex files to PDF, PdfLaTeX was missing.
I was really frustrated at that time because I don't like the mac version of LaTeX at all. You have to download a big package from https://www.tug.org/mactex/ which is huge, and I really like to work in my favorite text editor namely sublime text instead of the ugly GUI provided in the Mac Suite. This time I'm going to try something new.
Docker is a great tool for getting dev environment ready for me, and I've been using it for building GoLang command line tools since a few month ago. After some DuckDuckGo searching( Who uses Google nowadays), I found one person actually did some profound work for me. However, I don't like the way he uses the command. To make the world a better place, I wrote two scripts and added those to the Dockerfile. And here is how I did it.
- First of all, you need to install virtualbox, docker and docker-machine
I personally love homebrew, and use it to get almost all the tools I need. If you need to know more about how i did it, please check https://github.com/soleo/dotfiles
brew install docker docker-machine> brew cask install virtualbox
- Use the Dockerfile to build the image or pull from docker hub> FROM blang/latex> MAINTAINER
Xinjiang Shao <shaoxinjiang at gmail dot com>
ADD build /usr/bin/build
RUN chmod +x /usr/bin/build
ADD clean /usr/bin/clean
RUN chmod +x /usr/bin/clean
VOLUME /latex
WORKDIR /latex soleo/latex
You can find the Dockerfile in my soleo/latex repo, and run "docker build -t soleo/latex ." to get a local build or run "docker pull soleo/latex" to fetch from Docker Hub
- Run build to generate PDFs
After everything is done on docker side, run "docker run — rm -v pwd:/latex soleo/latex build
example.tex" to compile your tex files. The build script is simply to run pdflatex twice to get your
final pdf generated.
- Clean up if you need (Optional but I like it)
Finally, if you don't like the mess you created, run "docker run — rm -v pwd:/latex soleo/latex
clean" in order to get rid of all log files.
Things I Love about this approach
Docker is a very interesting project, I know this project since it was version 0.3, and now it grows so powerful. I saw great potentials to use it for dev environment setup, but this tool could be used for DevOps as well. Unfortunately, I still have to install VirtualBox and create a virtual machine in order to use docker, but at least I only need one virtual machine. In this approach, I could use whatever editor I like and compile it with one single command. The advantage of using docker for me in this case is that if I don't want to use the tools anymore, I could simply remove the images from my Macbook. It's just that simple.

