From b72577707c0d0250282df8811178d1c24db07d8a Mon Sep 17 00:00:00 2001 From: joergklein <38553171+joergklein@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:03:12 +0200 Subject: [PATCH] feat(templates): add docker-texlive template with code-server (#828) ## Description ## Type of Change - [ ] New module - [x] New template - [ ] Bug fix - [ ] Feature/enhancement - [ ] Documentation - [ ] Other ## Template Information **Path:** `registry/joergklein/templates/docker-texlive` ## Testing & Validation - [x] Tests pass (`bun test`) - [x] Code formatted (`bun fmt`) - [x] Changes tested locally ## Related Issues --------- Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: DevCats Co-authored-by: Atif Ali Co-authored-by: DevelopmentCats --- .icons/texlive.svg | 315 ++++++++++++++++++ registry/joergklein/.images/avatar.jpg | Bin 0 -> 1222 bytes registry/joergklein/README.md | 11 + .../templates/docker-texlive/README.md | 90 +++++ .../templates/docker-texlive/build/Dockerfile | 29 ++ .../templates/docker-texlive/main.tf | 200 +++++++++++ 6 files changed, 645 insertions(+) create mode 100644 .icons/texlive.svg create mode 100644 registry/joergklein/.images/avatar.jpg create mode 100644 registry/joergklein/README.md create mode 100644 registry/joergklein/templates/docker-texlive/README.md create mode 100644 registry/joergklein/templates/docker-texlive/build/Dockerfile create mode 100644 registry/joergklein/templates/docker-texlive/main.tf diff --git a/.icons/texlive.svg b/.icons/texlive.svg new file mode 100644 index 00000000..2d130393 --- /dev/null +++ b/.icons/texlive.svg @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/registry/joergklein/.images/avatar.jpg b/registry/joergklein/.images/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d71831071746c626bab51ad55dbdc08bb5ebf153 GIT binary patch literal 1222 zcmex=KU|?coW@chxW@Tkz0jjJ8$}zAA zvI;30I#U-U>$dGXcJ4ZK_{h;?$4{I*b?NeztJkjIxOwa0qsLF4K70P+<*SdM zK7aZ8?fZ|PzZe;qA>IL!5Dy{wM-b>ACKeWE7Iu(-7@5j}m|2j8Rnd@5$T5&Tu~1ma zsF6d&Y2w0-2RW6EgFc8R6KQ!#m{`Vr(Mu#brIP!m}`f_n(=pZ~WQc$gW15ymXY zV9)UU-?@}z<)=4y>Qt&+%UfvdYIWgckiEUD7gu~RGZlYgY`e3>LYbxBFsVK>7)KI+?!f4Jn* zD|)0zQR~%#)%q+lUq!cFJ9u4rp`>W&+KpNt@9p*z-uc`7-3NAy_YqO5cfZX}*l?Ih zf09S;;XdPIb&KVD%cR*39?yENwzKWtw|}C7o8R8!dN4(${0mTIqvnpgvJq}O-<&;Z z>Kh%fZF_d4*zKCEH+vn`*ZIqY)h%CgC###ss^?T<=7pTl{|pi4e9PBA{dIM&aZvuo zXro1LC*{t#{XQ)<>yh@{u zvvae)yqqQa^u@6k3F$Ha8LDOKcC2T-{B`$T;}ENsqTMHzh4mi)+iY9>KJM^Gt0%XA z=uVKS{Om6I{nh>7x)pl_X7&^=IK7)Se&vIJOIc@xGw;g1ToCtn(>;ErbI;GuQ!VMw zl-K5IvJUrOd1xQUhq#4n?rz8pis&&+_|W% [!NOTE] +> This template is designed to be a starting point! Edit the Terraform to extend it for your use case. + +## Customization + +The continuous integration is scheduled to rebuild all Docker images weekly. Hence, pulling the latest image will provide you with an at most one week old snapshot of TeX Live including all packages. You can manually update within the container by running `tlmgr update --self --all`. + +Each of the weekly builds is tagged with `TL{RELEASE}-{YEAR}-{MONTH}-{DAY}-{HOUR}-{MINUTE}` apart from being latest for one week. If you want to have reproducible builds or happen to find a regression in a later image you can still revert to a date that worked, e.g. `TL2019-2019-08-01-08-14 or latest`. + +- [Container Registry TeX Live](https://gitlab.com/islandoftex/images/texlive/container_registry) +- [Dockerhub TeX Live](https://hub.docker.com/r/texlive/texlive) + +### Installing additional TeX packages + +If you want to update packages from CTAN after installation, see these [examples of using tlmgr](https://tug.org/texlive/doc/tlmgr.html#EXAMPLES). This is not required, or even necessarily recommended; it's up to you to decide if it makes sense to get continuing updates in your particular situation. + +Typically the main binaries are not updated in TeX Live between major releases. If you want to get updates for LuaTeX and other packages and programs that aren't officially released yet, they may be available in the [TLContrib repository](http://contrib.texlive.info), or you may need to [compile the sources](https://tug.org/texlive/svn) yourself. + +### Adding system dependencies + +The `build/Dockerfile` extends the `registry.gitlab.com/islandoftex/images/texlive` base image with system packages required by modules (e.g. `curl` for code-server). If you add modules that need additional system-level tools, add them to the `Dockerfile`: + +```dockerfile +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + curl \ + inkscape \ + unzip \ + vim \ + wget \ + your-package-here \ + && rm -rf /var/lib/apt/lists/* +``` diff --git a/registry/joergklein/templates/docker-texlive/build/Dockerfile b/registry/joergklein/templates/docker-texlive/build/Dockerfile new file mode 100644 index 00000000..c8651e76 --- /dev/null +++ b/registry/joergklein/templates/docker-texlive/build/Dockerfile @@ -0,0 +1,29 @@ +# syntax=docker/dockerfile:1 + +ARG TEXLIVE_VERSION=latest +FROM registry.gitlab.com/islandoftex/images/texlive:${TEXLIVE_VERSION} + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + curl \ + inkscape \ + unzip \ + vim \ + wget \ + && rm -rf /var/lib/apt/lists/* + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +RUN useradd -m -s /bin/bash texlive || true + +ENV HOME=/home/texlive + +ENV TEXMFCNF=/home/texlive/texmf/web2c:/usr/local/texlive/2026/texmf-dist/web2c + +RUN mkdir -p /home/texlive/texmf/web2c \ + && echo "save_size = 300000" >/home/texlive/texmf/web2c/texmf.cnf \ + && chown -R texlive:texlive /home/texlive + +USER texlive +WORKDIR /home/texlive diff --git a/registry/joergklein/templates/docker-texlive/main.tf b/registry/joergklein/templates/docker-texlive/main.tf new file mode 100644 index 00000000..6747a53a --- /dev/null +++ b/registry/joergklein/templates/docker-texlive/main.tf @@ -0,0 +1,200 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +# ------------------------- +# Variables +# ------------------------- +variable "docker_socket" { + type = string + default = "" +} + +variable "texlive_version" { + type = string + default = "latest" +} + +# ------------------------- +# Provider +# ------------------------- +provider "docker" { + host = var.docker_socket != "" ? var.docker_socket : null +} + +# ------------------------- +# Coder data +# ------------------------- +data "coder_provisioner" "me" {} +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +# ------------------------- +# Locals +# ------------------------- +locals { + username = try(data.coder_workspace_owner.me.name, "unknown") + start_count = try(data.coder_workspace.me.start_count, 0) + + build_context_hash = sha1(join("", [ + for f in fileset("${path.module}/build", "**") : + try(filesha1("${path.module}/build/${f}"), "") + ])) +} + +# ------------------------- +# Coder Agent +# ------------------------- +resource "coder_agent" "main" { + arch = try(data.coder_provisioner.me.arch, "x86_64") + os = "linux" + + startup_script = <<-EOT + set -e + touch ~/.init_done + EOT + + env = { + HOME = "/home/texlive" + USER = "texlive" + LANG = "C.UTF-8" + LC_ALL = "C.UTF-8" + + GIT_AUTHOR_NAME = coalesce(try(data.coder_workspace_owner.me.full_name, ""), local.username) + GIT_AUTHOR_EMAIL = try(data.coder_workspace_owner.me.email, "unknown@example.com") + } + + metadata { + display_name = "CPU" + key = "cpu" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM" + key = "ram" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Disk" + key = "disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } +} + +# ------------------------- +# Code Server +# ------------------------- +module "code-server" { + count = local.start_count + source = "registry.coder.com/coder/code-server/coder" + version = "~> 1.0" + + agent_id = coder_agent.main.id + folder = "/home/texlive" +} + +# ------------------------- +# Docker Image +# ------------------------- +resource "docker_image" "texlive" { + name = "coder-${data.coder_workspace.me.id}-texlive" + + build { + context = "${path.module}/build" + dockerfile = "Dockerfile" + + build_args = { + TEXLIVE_VERSION = var.texlive_version + } + } + + keep_locally = false + + triggers = { + dir_hash = local.build_context_hash + texlive_version = var.texlive_version + } +} + +# ------------------------- +# Volume (correct docker provider syntax) +# ------------------------- +resource "docker_volume" "home_volume" { + name = "coder-${try(data.coder_workspace.me.id, 0)}-home" + + labels { + label = "coder.owner" + value = local.username + } + + labels { + label = "coder.workspace_id" + value = try(data.coder_workspace.me.id, "0") + } + + labels { + label = "coder.workspace_name" + value = try(data.coder_workspace.me.name, "workspace") + } + + lifecycle { + ignore_changes = all + } +} + +# ------------------------- +# Container +# ------------------------- +resource "docker_container" "workspace" { + count = local.start_count + + image = docker_image.texlive.image_id + name = "coder-${local.username}-${lower(try(data.coder_workspace.me.name, "workspace"))}" + hostname = try(data.coder_workspace.me.name, "workspace") + + entrypoint = [ + "sh", + "-c", + coder_agent.main.init_script + ] + + env = [ + "CODER_AGENT_TOKEN=${coder_agent.main.token}" + ] + + host { + host = "host.docker.internal" + ip = "host-gateway" + } + + volumes { + container_path = "/home/texlive" + volume_name = docker_volume.home_volume.name + read_only = false + } + + labels { + label = "coder.owner" + value = local.username + } + + labels { + label = "coder.workspace_id" + value = try(data.coder_workspace.me.id, "0") + } +}