├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── test ├── clean.sh └── minimal.tex ├── texlive-user ├── Dockerfile ├── build_container.sh ├── enter_container.sh ├── start_container.sh ├── stop_container.sh ├── test.sh └── with_container.sh ├── texlive ├── Dockerfile ├── build_container.sh ├── enter_container.sh ├── start_container.sh ├── stop_container.sh ├── test.sh └── with_container.sh └── travis.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .#* 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: shell 2 | os: linux 3 | dist: focal 4 | 5 | # Make "docker" available to the build environment so that we can use it to 6 | # build docker images, etc. 7 | services: 8 | - docker 9 | 10 | env: 11 | jobs: 12 | - DOCKERFILE_DIR=texlive 13 | DOCKERFILE_TAG=listx/texlive:2020 14 | - DOCKERFILE_DIR=texlive-user 15 | DOCKERFILE_TAG= 16 | 17 | before_script: 18 | - git branch 19 | - docker version 20 | - docker info 21 | - docker images 22 | 23 | script: 24 | # https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received 25 | - travis_wait 30 ./travis.sh 26 | 27 | after_success: 28 | - docker images 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2020, Linus Arver. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TexLive Docker Images 2 | 3 | [![Build Status](https://travis-ci.org/listx/texlive-docker.svg?branch=master)](https://travis-ci.org/listx/texlive-docker) 4 | ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/listx/texlive/2020) 5 | [![Docker hub](https://img.shields.io/docker/pulls/listx/texlive.svg)](https://hub.docker.com/r/listx/texlive/) 6 | 7 | This repository holds the Dockerfiles that are used to build Docker images of 8 | TexLive, which are hosted on [Docker Hub][docker-hub]. 9 | 10 | # Tutorial 11 | 12 | There is 1 image, called 13 | 14 | - `listx/texlive:2020` 15 | 16 | which this repo publishes. To use this image, simply run the 17 | [`start_container.sh`](./texlive/start_container.sh) script in the 18 | [`texlive`](./texlive) subfolder. 19 | 20 | ``` 21 | cd texlive 22 | ./start_container.sh 23 | ``` 24 | 25 | `start_container.sh` mounts the `/home` folder (which should house your `$HOME` 26 | folder, which presumably has your TeX files needing compilation) into the 27 | container, and keeps it running in the background. Now you can either invoke 28 | [`enter_container.sh`](./texlive/enter_container.sh) to enter a TexLive bash 29 | environment inside the container, or you can optionally run 30 | [`with_container.sh`](./texlive/with_container.sh) to invoke a build script for 31 | your TeX files if you already have such a build script ready, with 32 | 33 | ``` 34 | cd texlive 35 | ./with_container.sh "path/to/your/tex/document/build/script.sh" 36 | ``` 37 | 38 | The above commands run everything as `root` inside the container. If you do not 39 | want this, go to the [`texlive-user`](./texlive-user) subfolder and run 40 | [`./build_container.sh`](texlive-user/build_container.sh) to generate an image 41 | that uses `listx/texlive:2020` as the base image but also injects a new user 42 | **inside** the container named after your current non-root user that has the 43 | same user ID and group ID as your own. Running that script will result in a new 44 | image with the tag `2020-${USER}` (named after your own username), and to use 45 | it you can invoke it the same way as for the root user, by invoking the 46 | `start_container.sh` script in the [`texlive-user`](./texlive-user) subfolder. 47 | The same guidance for `enter_container.sh` and `with_container.sh` apply here 48 | as well. 49 | 50 | # License 51 | 52 | See [LICENSE file](LICENSE). 53 | 54 | [docker-hub]: https://hub.docker.com/r/listx/texlive 55 | -------------------------------------------------------------------------------- /test/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | set -o xtrace 7 | 8 | PROJECT_ROOT=$(git rev-parse --show-toplevel) 9 | 10 | shopt -s extglob 11 | 12 | # Remove all auxiliary TeX files. 13 | rm -fv ${PROJECT_ROOT}/test/minimal.!(tex) 14 | 15 | # Remove auxiliary latexindent files. 16 | rm -f indent.log 17 | -------------------------------------------------------------------------------- /test/minimal.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[margin=1in]{geometry} 3 | 4 | \begin{document} 5 | 6 | Hello world! 7 | 8 | \end{document} 9 | -------------------------------------------------------------------------------- /texlive-user/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM listx/texlive:2020 2 | 3 | ARG user 4 | ARG group 5 | ARG uid 6 | ARG gid 7 | 8 | RUN \ 9 | addgroup -g ${gid} ${group} \ 10 | && echo -e "${user}\n${user}" | adduser -G ${group} -u ${uid} ${user} 11 | 12 | # Use "${user}" user. 13 | USER ${user} 14 | -------------------------------------------------------------------------------- /texlive-user/build_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | __user=$(id -u -n) 8 | __group=$(id -g -n) 9 | __uid=$(id -u) 10 | __gid=$(id -g) 11 | 12 | docker build \ 13 | --build-arg user=${__user} \ 14 | --build-arg group=${__group} \ 15 | --build-arg uid=${__uid} \ 16 | --build-arg gid=${__gid} \ 17 | --tag "${1:-listx/texlive:2020-${__user}}" . 18 | -------------------------------------------------------------------------------- /texlive-user/enter_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | docker exec -it "$@" texlive2020-$(id -u -n) bash 8 | -------------------------------------------------------------------------------- /texlive-user/start_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | set -o xtrace 7 | 8 | __user=$(id -u -n) 9 | 10 | __container_name=texlive2020-${__user} 11 | 12 | __container_id="$(docker ps -f name=${__container_name} -q)" 13 | 14 | # Only run a container if it isn't already running. 15 | if [[ -n "${__container_id}" ]]; then 16 | echo "${__container_name} is already running" 17 | else 18 | docker run -d --rm -v /home:/home --name ${__container_name} listx/texlive:2020-${__user} 19 | fi 20 | -------------------------------------------------------------------------------- /texlive-user/stop_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | __user=$(id -u -n) 8 | 9 | docker stop texlive2020-${__user} 10 | -------------------------------------------------------------------------------- /texlive-user/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | PROJECT_ROOT=$(git rev-parse --show-toplevel) 8 | 9 | # Ensure we can build with the user-based container. 10 | "${PROJECT_ROOT}"/texlive-user/start_container.sh 11 | "${PROJECT_ROOT}"/texlive-user/with_container.sh "cd ${PROJECT_ROOT}/test && pdflatex minimal.tex" 12 | if [[ ! -f "${PROJECT_ROOT}/test/minimal.pdf" ]]; then 13 | echo >&2 "could not compile ${PROJECT_ROOT}/test/minimal.pdf" 14 | exit 1 15 | fi 16 | owner_user=$(stat -c %U "${PROJECT_ROOT}/test/minimal.pdf") 17 | owner_group=$(stat -c %G "${PROJECT_ROOT}/test/minimal.pdf") 18 | 19 | # Ensure that the file was generated as a normal user. 20 | if [[ "${owner_user}" != $(id -u -n) ]]; then 21 | echo >&2 "${PROJECT_ROOT}/test/minimal.pdf is owned by UID ${owner_user}; expected $(id -u -n)" 22 | exit 1 23 | fi 24 | if [[ "${owner_group}" != $(id -g -n) ]]; then 25 | echo >&2 "${PROJECT_ROOT}/test/minimal.pdf is owned by GID ${owner_group}; expected $(id -g -n)" 26 | exit 1 27 | fi 28 | 29 | # Cleanup. 30 | "${PROJECT_ROOT}"/texlive-user/with_container.sh "cd ${PROJECT_ROOT}/test && ./clean.sh" 31 | -------------------------------------------------------------------------------- /texlive-user/with_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | set -o xtrace 7 | 8 | docker exec \ 9 | texlive2020-$(id -u -n) \ 10 | bash -c "$*" 11 | -------------------------------------------------------------------------------- /texlive/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nixos/nix 2 | 3 | MAINTAINER Linus Arver 4 | 5 | RUN \ 6 | nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs \ 7 | && nix-channel --update \ 8 | # Install packages. 9 | && nix-env -f '' -iA \ 10 | bashInteractive \ 11 | git \ 12 | python39Packages.pygments \ 13 | texlive.combined.scheme-full \ 14 | # Clean up unusued paths. 15 | && nix-collect-garbage -d 16 | 17 | CMD ["tail", "-f", "/dev/null"] 18 | 19 | # REFERENCES 20 | # [1]: https://www.reddit.com/r/archlinux/comments/5ash5v/problem_with_biber/ 21 | -------------------------------------------------------------------------------- /texlive/build_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | docker build --tag "${1:-listx/texlive:2020}" . 8 | -------------------------------------------------------------------------------- /texlive/enter_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | docker exec -it "$@" texlive2020-root bash 8 | -------------------------------------------------------------------------------- /texlive/start_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | set -o xtrace 7 | 8 | __container_name=texlive2020-root 9 | 10 | __container_id="$(docker ps -f name=${__container_name} -q)" 11 | 12 | # Only run a container if it isn't already running. 13 | if [[ -n "${__container_id}" ]]; then 14 | echo "${__container_name} is already running" 15 | else 16 | docker run -d --rm -v /home:/home --name ${__container_name} listx/texlive:2020 17 | fi 18 | -------------------------------------------------------------------------------- /texlive/stop_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | docker stop texlive2020-root 8 | -------------------------------------------------------------------------------- /texlive/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | PROJECT_ROOT=$(git rev-parse --show-toplevel) 8 | 9 | # Ensure we can build with the basic container. 10 | "${PROJECT_ROOT}"/texlive/start_container.sh 11 | "${PROJECT_ROOT}"/texlive/with_container.sh "cd ${PROJECT_ROOT}/test && pdflatex minimal.tex" 12 | if [[ ! -f ${PROJECT_ROOT}/test/minimal.pdf ]]; then 13 | echo >&2 "could not compile ${PROJECT_ROOT}/test/minimal.pdf" 14 | exit 1 15 | fi 16 | 17 | # Test that latexindent can run against minimal.tex. 18 | "${PROJECT_ROOT}"/texlive/with_container.sh "cd ${PROJECT_ROOT}/test && latexindent minimal.tex" 19 | 20 | # Cleanup. 21 | "${PROJECT_ROOT}"/texlive/with_container.sh "cd ${PROJECT_ROOT}/test && ./clean.sh" 22 | -------------------------------------------------------------------------------- /texlive/with_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | set -o xtrace 7 | 8 | docker exec \ 9 | texlive2020-root \ 10 | bash -c "$*" 11 | -------------------------------------------------------------------------------- /travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | # From https://stackoverflow.com/a/8574392/437583. 8 | includes() 9 | { 10 | local match="$1" 11 | local element 12 | shift 13 | for element; do 14 | [[ "$element" == "$match" ]] && return 0 15 | done 16 | return 1 17 | } 18 | 19 | # Logic for checking required variables inspired by 20 | # http://unix.stackexchange.com/a/278974/72230. 21 | required_vars=( 22 | DOCKER_USER 23 | DOCKER_PASSWORD 24 | DOCKERFILE_DIR 25 | ) 26 | missing_vars=() 27 | # According to "Shell Parameter Expansion", the "!" in ${!...} introduces a 28 | # level of indirection; it basically uses the *value* of the variable to access 29 | # another variable. 30 | for var in "${required_vars[@]}"; do 31 | if [[ -z "${!var:+x}" ]]; then 32 | missing_vars+=("$var") 33 | fi 34 | done 35 | 36 | if (( ${#missing_vars[@]} != 0 )); then 37 | echo "The following variables are not set, or are set to the empty string:" >&2 38 | printf ' %q\n' "${missing_vars[@]}" >&2 39 | exit 1 40 | fi 41 | 42 | if [[ ! -d $DOCKERFILE_DIR ]]; then 43 | "directory \`$DOCKERFILE_DIR' does not exist " 44 | exit 1 45 | fi 46 | 47 | to_push=( 48 | # Only push the Docker image built in the "texlive" subdirectory. 49 | texlive 50 | ) 51 | 52 | pushd "${DOCKERFILE_DIR}" 53 | 54 | echo "### Building container" 55 | ./build_container.sh 56 | 57 | echo "### Testing" 58 | ./test.sh 59 | 60 | if includes "${DOCKERFILE_DIR}" "${to_push[@]}"; then 61 | # For those images we want to push, we must be provided an explicit tag 62 | # to use for pushing. 63 | if [[ -z "${DOCKERFILE_TAG:-}" ]]; then 64 | echo "image push: missing \$DOCKERFILE_TAG" >&2 65 | exit 1 66 | fi 67 | 68 | # Only push images for master branch. This way "next" branch can be 69 | # used purely for testing only. 70 | if [[ $(git rev-parse --abbrev-ref HEAD) == "master" ]]; then 71 | docker login -u "$DOCKER_USER" -p "$DOCKER_PASSWORD" 72 | docker push "$DOCKERFILE_TAG" 73 | fi 74 | fi 75 | 76 | popd 77 | --------------------------------------------------------------------------------