commit b083b6249513e199d3f12a0fbe69dab39d12fbca Author: Dominik Agres Date: Mon Jun 22 23:56:48 2026 +0200 initial image diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..506244d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,59 @@ +name: build + +on: + push: + branches: [main] + workflow_dispatch: + +env: + IMAGE: ghcr.io/agresdominik/texlive + +jobs: + build: + name: build ${{ matrix.arch }} + runs-on: ${{ matrix.runner }} + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + include: + - { runner: ubuntu-24.04, arch: amd64 } + - { runner: ubuntu-24.04-arm, arch: arm64 } + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/${{ matrix.arch }} + push: true + tags: ${{ env.IMAGE }}:${{ github.sha }}-${{ matrix.arch }} + cache-from: type=gha,scope=${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=${{ matrix.arch }} + + manifest: + name: merge manifest + needs: build + runs-on: ubuntu-24.04 + permissions: + packages: write + steps: + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Create multi-arch manifests + run: | + for tag in latest "${GITHUB_SHA}"; do + docker buildx imagetools create -t "${IMAGE}:${tag}" \ + "${IMAGE}:${GITHUB_SHA}-amd64" \ + "${IMAGE}:${GITHUB_SHA}-arm64" + done diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fbb8f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# LaTeX build artifacts +*.aux +*.bbl +*.bcf +*.blg +*.fdb_latexmk +*.fls +*.lof +*.log +*.lot +*.out +*.run.xml +*.synctex.gz +*.toc +*.nav +*.snm +*.vrb +*.xdv + +# Output (uncomment if you don't want PDFs tracked) +# *.pdf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..341edc2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM debian:trixie-slim + +# texlive-full already pulls latexmk + biber; listed explicitly so intent is clear. +RUN apt-get update && apt-get install -y --no-install-recommends \ + texlive-full \ + latexmk \ + biber \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /data +ENTRYPOINT ["latexmk"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0fa0130 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Dominik Agres + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a2318d --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# texlive + +A "batteries-included" LaTeX toolchain in a Docker image: `texlive-full` + +`latexmk` + `biber` on `debian:trixie-slim`. Built for academic writing — +heavy math, `biblatex`/`biber`, TikZ/pgfplots, German `babel` + `fontspec`. + +Multi-arch: `linux/amd64` and `linux/arm64`, so it runs natively on an Asahi +Mac (arm64) and an Arch desktop (amd64) alike. + +``` +ghcr.io/agresdominik/texlive:latest +``` + +## Pull + +```sh +docker pull ghcr.io/agresdominik/texlive:latest +``` + +Docker picks the right arch from the manifest automatically. + +## Use + +The image's entrypoint is `latexmk` with `WORKDIR /data`, so anything after +the image name is passed straight to `latexmk`. + +### `tex` wrapper + +Mounts the current directory into the container and fixes file ownership so +output isn't root-owned (`--user` + a writable `HOME` for TeX's cache). + +zsh function — drop into `~/.zshrc`: + +```zsh +tex() { + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -e HOME=/tmp \ + -v "$PWD:/data" \ + ghcr.io/agresdominik/texlive:latest "$@" +} +``` + +Or use the standalone [`tex`](./tex) script — put it on your `$PATH`: + +```sh +install -m755 tex ~/.local/bin/tex +``` + +Then: + +```sh +tex -pdf main.tex # build +tex -pvc main.tex # watch + rebuild +tex -C # clean aux files +``` + +## How the multi-arch build works + +`.github/workflows/build.yml` builds **natively per arch** — no QEMU: + +1. A matrix `build` job runs once on `ubuntu-24.04` (amd64) and once on + `ubuntu-24.04-arm` (arm64). Each builds for its own platform and pushes a + per-arch tag: `:-amd64`, `:-arm64`. +2. A final `manifest` job merges those into single multi-arch tags with + `docker buildx imagetools create`, publishing both `:latest` and `:`. + +Auth is `GITHUB_TOKEN` with `packages: write`, logging in to `ghcr.io`. +Triggers: push to `main` and manual `workflow_dispatch`. + +## Trimming the image later + +`texlive-full` is large (multiple GB). If size becomes a problem, swap the +Debian package for a custom TeX Live install driven by a `texlive.profile`, +selecting `scheme-full` down to e.g. `scheme-medium` plus only the collections +you need (`collection-latexextra`, `collection-bibtexextra`, +`collection-pictures`, `collection-langgerman`, `collection-fontsrecommended`, +…). Build with `install-tl --profile texlive.profile`, then `tlmgr install` +any stragglers. Keep `scheme-full` until the size actually hurts. + +## License + +MIT — see [LICENSE](./LICENSE). diff --git a/tex b/tex new file mode 100755 index 0000000..bf1f31a --- /dev/null +++ b/tex @@ -0,0 +1,9 @@ +#!/bin/sh +# Run latexmk from the texlive image against the current directory. +# tex -pdf main.tex +# --user + HOME=/tmp keep build artifacts owned by you, not root. +exec docker run --rm \ + --user "$(id -u):$(id -g)" \ + -e HOME=/tmp \ + -v "$PWD:/data" \ + ghcr.io/agresdominik/texlive:latest "$@"