Git, Docker, and continuous integration for TeX documents

No readers like this yet.
left and right brain

The power of Git, Docker, and continuous integration (CI) can be leveraged to make TeX document compilation easy while keeping track of different variants and versions. On the top of these technologies, a flexible workflow can be developed to reflect successive changes in TeX documents in each PDF—versioned with a progressive number, document-v4.pdf, say. So, let's create a workflow that can automate the process for us.

1. Objective

Use Git, Docker, and continuous integration (CI) to build TeX documents and upload the PDF to Dropbox with a proper branch structure and versioning.

2. Workflow

Git, Docker, and continuous integration diagram

3. Requirements

We need:

  1. Git service
    • Bitbucket
    • GitHub
  2. Continuous integration and deployment service
    • Semaphore
    • Travis
  3. Dropbox account

3.1. Dropbox Uploader

Note: While configuring Dropbox API, use of App Folder only as access level is recommended.

To upload generated PDF to Dropbox, we will use Dropbox Uploader.

  1. Follow Dropbox Uploader's and configure it on your local machine.
  2. Verify that you have ~/.dropbox_uploader file on your local machine. We will use this file later.

4. Prepare Git repository

See best practices for writing Dockerfiles.

Initialize Git (git init) and use following directory structure for your git repository:

├── docker
|   ├── Dockerfile
├── document.tex

Now for docker/Dockerfile, we will use harshjv/texlive-2015 docker image. This image contains TeX Live 2015.

4.1. Dockerfile

FROM harshjv/texlive-2015
RUN tlmgr update --self --all

This will build Docker image with latest packages for building TeX documents.

5. Add your TeX documents

Add some TeX files to your repository.

6. Configure Git service

For Webhooks/Services, we need to configure Git services as follows;

6.1. For Bitbucket

No configuration needed as of now.

6.2. For GitHub

  1. Go to your repository's Settings -> Webhooks & services -> Services
  2. Select Travis CI

7. Configure continuous integration service

7.1. For Semaphore

  1. Do an initial commit and push to remote branch (if empty remote repository), because it requires, at least, one remote branch.
  2. Go to SemaphoreCI
  3. Add new project
  4. Select your Git service
  5. Select your repository
  6. Select branch (e.g., master)

7. Select your account

After these initial steps, now it's time to configure build and deployment.

7.1.1. Setup thread

This setup script builds docker/Dockerfile with latest TeX packages and fetches Dropbox Uploader script.

sudo docker build -t texlive docker
curl "" -o
chmod +x

7.1.2. Build Thread

Note: For document.lex in master branch, document.pdf will be uploaded as:


This build script compiles document.lex LeX document and builds document.pdf PDF. Then, using Dropbox Uploader, versioned PDF files are stored in branch's individual folder.

sudo docker run -it -v ${SEMAPHORE_PROJECT_DIR}:/var/texlive texlive sh -c "pdflatex document.lex"
./ upload document.pdf ${BRANCH_NAME}/document-latest.pdf
./ upload document.pdf ${BRANCH_NAME}/document-v${SEMAPHORE_BUILD_NUMBER}.pdf

Any successive commit will overwrite document-latest.pdf and will create a new document-v[BUILD_NUMBER].pdf file.

7.1.3. Configuration Files

  1. Visit Project Settings -> Configuration Files
  2. Add configuration file
  3. Add .dropbox_uploader to file path
  4. (Optional) Check encryption
  5. Paste content of ~/.dropbox_uploader
    • In MacOS X, pbcopy ~/.dropbox_uploader

7.2. For Travis

The script for setup procedure and building remains the same. Put these scripts into individual files and create a .travis.yml file. Refer this post for relevant instructions.

8. Git commit and push

It's time to push the documents/changes.

git add .
git commit -m "Add some details"
git push origin master

9. Success!

Tip: If you want to share only the latest PDF after changes, use URL shortener service like to point to this latest document after getting sharing link from Dropbox.

Why? Because for each branch folder, [DOCUMENT_NAME]-latest.pdf will always contain latest PDF.

After a successful build, generated PDF files will be available at Dropbox/[YOUR_APP_FOLDER]/master folder.

Harsh Vakharia
I’m pursuing a bachelor's degree in Computer Engineering. Apart from the curriculum, I’ve built android and web applications during past 3 years and I'm working on ML and NLP nowadays. I love open sources things and code wise, C, C++, Python, Java and PHP are my languages of choice. You can find me on Github and twitter @harshjv.


Interesting methodology! If I'm reading this right, it would be trivial to replace at least the Dropbox step with any given web server, yes? I mean, the Dropbox step does not add anything to your setup; it's just the delivery platform, correct?

Thanks for an interesting article.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.