Skip to content

Commit b725777

Browse files
joergkleinblink-so[bot]DevelopmentCatsmatifali
authored
feat(templates): add docker-texlive template with code-server (#828)
## Description <!-- Briefly describe what this PR does and why --> ## 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 <!-- Link related issues or write "None" if not applicable --> --------- Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: DevCats <chris@dualriver.com> Co-authored-by: Atif Ali <atif@coder.com> Co-authored-by: DevelopmentCats <christofer@coder.com>
1 parent 9c01790 commit b725777

6 files changed

Lines changed: 645 additions & 0 deletions

File tree

.icons/texlive.svg

Lines changed: 315 additions & 0 deletions
Loading
1.19 KB
Loading

registry/joergklein/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
display_name: "Jörg Klein"
3+
bio: "Data Scientists"
4+
github: "joergklein"
5+
avatar: "./.images/avatar.jpg"
6+
status: "community"
7+
---
8+
9+
# Jörg Klein
10+
11+
Data Scientists
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
display_name: Docker TeX Live
3+
description: Provision Docker containers with TeX Live, code-server
4+
icon: ../../../../.icons/texlive.svg
5+
tags: [docker, texlive]
6+
---
7+
8+
# TeX Live Development on Docker Containers
9+
10+
Provision Docker containers pre-configured for TeX development as [Coder workspaces](https://coder.com/docs/workspaces) with this template.
11+
12+
Each workspace comes with:
13+
14+
- **TeX Live** — TeX Live is a comprehensive, cross-platform distribution for TeX and LaTeX systems that provides all necessary programs, macro packages, and fonts for professional typesetting.
15+
- **code-server** — VS Code in the browser for general editing.
16+
17+
The workspace is based on the [TeX Live](https://www.tug.org/texlive) image. It provides nearly all packages from the [Comprehensive TeX Archive Network (CTAN)](https://www.ctan.org), although some non-free packages may be restricted.
18+
19+
## Prerequisites
20+
21+
### Infrastructure
22+
23+
#### Running Coder inside Docker
24+
25+
If you installed Coder as a container within Docker, you will have to do the following things:
26+
27+
- Make the Docker socket available to the container
28+
- **(recommended) Mount `/var/run/docker.sock` via `--mount`/`volume`**
29+
- _(advanced) Restrict the Docker socket via https://github.com/Tecnativa/docker-socket-proxy_
30+
- Set `--group-add`/`group_add` to the GID of the Docker group on the **host** machine
31+
- You can get the GID by running `getent group docker` on the **host** machine
32+
33+
#### Running Coder outside of Docker
34+
35+
If you installed Coder as a system package, the VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:
36+
37+
```bash
38+
# Add coder user to Docker group
39+
sudo adduser coder docker
40+
41+
# Restart Coder server
42+
sudo systemctl restart coder
43+
44+
# Test Docker
45+
sudo -u coder docker ps
46+
```
47+
48+
## Architecture
49+
50+
This template provisions the following resources:
51+
52+
- Docker image (built from `build/Dockerfile`, extending `registry.gitlab.com/islandoftex/images/texlive` with system dependencies)
53+
- Docker container (ephemeral — destroyed on workspace stop)
54+
- Docker volume (persistent on `/home/texlive`)
55+
56+
When the workspace restarts, tools and files outside `/home/texlive` are not persisted.
57+
58+
> [!NOTE]
59+
> This template is designed to be a starting point! Edit the Terraform to extend it for your use case.
60+
61+
## Customization
62+
63+
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`.
64+
65+
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`.
66+
67+
- [Container Registry TeX Live](https://gitlab.com/islandoftex/images/texlive/container_registry)
68+
- [Dockerhub TeX Live](https://hub.docker.com/r/texlive/texlive)
69+
70+
### Installing additional TeX packages
71+
72+
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.
73+
74+
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.
75+
76+
### Adding system dependencies
77+
78+
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`:
79+
80+
```dockerfile
81+
RUN apt-get update \
82+
&& apt-get install -y --no-install-recommends \
83+
curl \
84+
inkscape \
85+
unzip \
86+
vim \
87+
wget \
88+
your-package-here \
89+
&& rm -rf /var/lib/apt/lists/*
90+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# syntax=docker/dockerfile:1
2+
3+
ARG TEXLIVE_VERSION=latest
4+
FROM registry.gitlab.com/islandoftex/images/texlive:${TEXLIVE_VERSION}
5+
6+
RUN apt-get update \
7+
&& apt-get install -y --no-install-recommends \
8+
curl \
9+
inkscape \
10+
unzip \
11+
vim \
12+
wget \
13+
&& rm -rf /var/lib/apt/lists/*
14+
15+
ENV LANG=C.UTF-8
16+
ENV LC_ALL=C.UTF-8
17+
18+
RUN useradd -m -s /bin/bash texlive || true
19+
20+
ENV HOME=/home/texlive
21+
22+
ENV TEXMFCNF=/home/texlive/texmf/web2c:/usr/local/texlive/2026/texmf-dist/web2c
23+
24+
RUN mkdir -p /home/texlive/texmf/web2c \
25+
&& echo "save_size = 300000" >/home/texlive/texmf/web2c/texmf.cnf \
26+
&& chown -R texlive:texlive /home/texlive
27+
28+
USER texlive
29+
WORKDIR /home/texlive
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
}
6+
docker = {
7+
source = "kreuzwerker/docker"
8+
}
9+
}
10+
}
11+
12+
# -------------------------
13+
# Variables
14+
# -------------------------
15+
variable "docker_socket" {
16+
type = string
17+
default = ""
18+
}
19+
20+
variable "texlive_version" {
21+
type = string
22+
default = "latest"
23+
}
24+
25+
# -------------------------
26+
# Provider
27+
# -------------------------
28+
provider "docker" {
29+
host = var.docker_socket != "" ? var.docker_socket : null
30+
}
31+
32+
# -------------------------
33+
# Coder data
34+
# -------------------------
35+
data "coder_provisioner" "me" {}
36+
data "coder_workspace" "me" {}
37+
data "coder_workspace_owner" "me" {}
38+
39+
# -------------------------
40+
# Locals
41+
# -------------------------
42+
locals {
43+
username = try(data.coder_workspace_owner.me.name, "unknown")
44+
start_count = try(data.coder_workspace.me.start_count, 0)
45+
46+
build_context_hash = sha1(join("", [
47+
for f in fileset("${path.module}/build", "**") :
48+
try(filesha1("${path.module}/build/${f}"), "")
49+
]))
50+
}
51+
52+
# -------------------------
53+
# Coder Agent
54+
# -------------------------
55+
resource "coder_agent" "main" {
56+
arch = try(data.coder_provisioner.me.arch, "x86_64")
57+
os = "linux"
58+
59+
startup_script = <<-EOT
60+
set -e
61+
touch ~/.init_done
62+
EOT
63+
64+
env = {
65+
HOME = "/home/texlive"
66+
USER = "texlive"
67+
LANG = "C.UTF-8"
68+
LC_ALL = "C.UTF-8"
69+
70+
GIT_AUTHOR_NAME = coalesce(try(data.coder_workspace_owner.me.full_name, ""), local.username)
71+
GIT_AUTHOR_EMAIL = try(data.coder_workspace_owner.me.email, "unknown@example.com")
72+
}
73+
74+
metadata {
75+
display_name = "CPU"
76+
key = "cpu"
77+
script = "coder stat cpu"
78+
interval = 10
79+
timeout = 1
80+
}
81+
82+
metadata {
83+
display_name = "RAM"
84+
key = "ram"
85+
script = "coder stat mem"
86+
interval = 10
87+
timeout = 1
88+
}
89+
90+
metadata {
91+
display_name = "Disk"
92+
key = "disk"
93+
script = "coder stat disk --path $${HOME}"
94+
interval = 60
95+
timeout = 1
96+
}
97+
}
98+
99+
# -------------------------
100+
# Code Server
101+
# -------------------------
102+
module "code-server" {
103+
count = local.start_count
104+
source = "registry.coder.com/coder/code-server/coder"
105+
version = "~> 1.0"
106+
107+
agent_id = coder_agent.main.id
108+
folder = "/home/texlive"
109+
}
110+
111+
# -------------------------
112+
# Docker Image
113+
# -------------------------
114+
resource "docker_image" "texlive" {
115+
name = "coder-${data.coder_workspace.me.id}-texlive"
116+
117+
build {
118+
context = "${path.module}/build"
119+
dockerfile = "Dockerfile"
120+
121+
build_args = {
122+
TEXLIVE_VERSION = var.texlive_version
123+
}
124+
}
125+
126+
keep_locally = false
127+
128+
triggers = {
129+
dir_hash = local.build_context_hash
130+
texlive_version = var.texlive_version
131+
}
132+
}
133+
134+
# -------------------------
135+
# Volume (correct docker provider syntax)
136+
# -------------------------
137+
resource "docker_volume" "home_volume" {
138+
name = "coder-${try(data.coder_workspace.me.id, 0)}-home"
139+
140+
labels {
141+
label = "coder.owner"
142+
value = local.username
143+
}
144+
145+
labels {
146+
label = "coder.workspace_id"
147+
value = try(data.coder_workspace.me.id, "0")
148+
}
149+
150+
labels {
151+
label = "coder.workspace_name"
152+
value = try(data.coder_workspace.me.name, "workspace")
153+
}
154+
155+
lifecycle {
156+
ignore_changes = all
157+
}
158+
}
159+
160+
# -------------------------
161+
# Container
162+
# -------------------------
163+
resource "docker_container" "workspace" {
164+
count = local.start_count
165+
166+
image = docker_image.texlive.image_id
167+
name = "coder-${local.username}-${lower(try(data.coder_workspace.me.name, "workspace"))}"
168+
hostname = try(data.coder_workspace.me.name, "workspace")
169+
170+
entrypoint = [
171+
"sh",
172+
"-c",
173+
coder_agent.main.init_script
174+
]
175+
176+
env = [
177+
"CODER_AGENT_TOKEN=${coder_agent.main.token}"
178+
]
179+
180+
host {
181+
host = "host.docker.internal"
182+
ip = "host-gateway"
183+
}
184+
185+
volumes {
186+
container_path = "/home/texlive"
187+
volume_name = docker_volume.home_volume.name
188+
read_only = false
189+
}
190+
191+
labels {
192+
label = "coder.owner"
193+
value = local.username
194+
}
195+
196+
labels {
197+
label = "coder.workspace_id"
198+
value = try(data.coder_workspace.me.id, "0")
199+
}
200+
}

0 commit comments

Comments
 (0)