5.8 KiB
Roc Language OCI Images
Date: 2026-06-04 Status: Design — approved
Overview
Build and publish OCI container images for the Roc language compiler/development environment. Three images (base, dev, ci) defined in a single multi-stage Containerfile, published to a self-hosted Gitea container registry (git.roo.lol).
Image Architecture
debian:bookworm-slim
└── roc-tools-base — Roc compiler binary + lib/wasi-libc.a + LICENSE
├── roc-tools-dev — Base + LSP + git + curl + bash + ca-certificates
└── roc-tools-ci — Base + ca-certificates (minimal runner)
Repository Structure
roc-lang-tools/
├── Containerfile # Multi-stage: base / dev / ci targets
├── Makefile # Build & push convenience commands
├── scripts/
│ └── download-roc.sh # Download & extract a specific Roc release tarball
├── docs/
│ └── specs/
│ └── 2026-06-04-roc-oci-images-design.md
└── .gitea/
└── workflows/
└── build.yaml # Gitea Actions CI: build & push on version tags
Image Registry
All images published to git.roo.lol/jbrechtel/ with the following naming:
| Image | Repository | Tags |
|---|---|---|
| base | git.roo.lol/jbrechtel/roc-tools-base |
:X.Y.Z, :X.Y.Z-alphaN |
| dev | git.roo.lol/jbrechtel/roc-tools-dev |
:X.Y.Z, :X.Y.Z-alphaN |
| ci | git.roo.lol/jbrechtel/roc-tools-ci |
:X.Y.Z, :X.Y.Z-alphaN |
Tags mirror Roc release tags (e.g., 0.0.0-alpha2). The :latest tag follows the most recently built version tag.
Build Arguments
The Containerfile accepts two build arguments:
| Argument | Description | Default |
|---|---|---|
ROC_VERSION |
Roc GitHub release tag to download | 0.0.0-alpha2 |
TARGETARCH |
Target CPU architecture (set by buildx) | amd64 |
Multi-arch is supported via docker buildx — the download script maps TARGETARCH to Roc tarball names (x86_64 / aarch64).
Image Details
Base (roc-tools-base)
The base image provides just the Roc compiler and its runtime library.
Installed:
/opt/roc/bin/roc— Roc compiler binary/opt/roc/lib/wasi-libc.a— WASI libc runtime library (required by some platforms)/opt/roc/LICENSE— Roc license fileca-certificates(build-time only, removed from final layer)rocuser/group (UID 1000)PATHincludes/opt/roc/bin
Entrypoint: roc
Dev (roc-tools-dev)
Full interactive development environment.
Inherits: Base image
Additional packages: git, curl, bash, ca-certificates
Additional files:
/opt/roc/bin/roc_language_server— Roc LSP server (included in the release tarball)
Entrypoint: bash
Use case:
docker run -it --rm -v $(pwd):/work -w /work git.roo.lol/jbrechtel/roc-tools-dev
CI (roc-tools-ci)
Minimal image for CI/CD runner pipelines (Gitea Actions, GitLab CI, etc.).
Inherits: Base image
Additional packages: ca-certificates
Entrypoint: roc
Use case:
- run: docker run --rm git.roo.lol/jbrechtel/roc-tools-ci roc build
Release Download Strategy
The scripts/download-roc.sh script:
- Accepts
ROC_VERSIONandTARGETARCHarguments - Constructs the GitHub release URL:
Where
https://github.com/roc-lang/roc/releases/download/{ROC_VERSION}/roc-linux_{ARCH}-{ROC_VERSION}.tar.gzARCHisx86_64(for amd64) oraarch64(for arm64). - Downloads and extracts the tarball
- Copies the
rocandroc_language_serverbinaries to/opt/roc/bin/ - Copies
lib/wasi-libc.ato/opt/roc/lib/ - Copies
LICENSEto/opt/roc/
The tarball contains a top-level directory with a nightly-derived name (e.g., roc_nightly-linux_x86_64-2025-09-09-d73ea109/), so the script uses a glob/wildcard rather than assuming a fixed directory name.
Build Workflow
Local Development
# Build all three images
make build-all ROC_VERSION=0.0.0-alpha2
# Build a specific target
make build-dev ROC_VERSION=0.0.0-alpha2
# Build and push
make push-all ROC_VERSION=0.0.0-alpha2
# Override registry
make build-base ROC_VERSION=0.0.0-alpha2 REGISTRY=localhost:5000
CI/CD (Gitea Actions)
The .gitea/workflows/build.yaml workflow triggers on Git tags matching v* (e.g., v0.0.0-alpha2). It:
- Extracts the Roc version from the tag (
v0.0.0-alpha2→0.0.0-alpha2) - Sets up Docker Buildx with multi-arch support (linux/amd64, linux/arm64)
- Logs into the Gitea container registry using the Gitea Actions token
- Builds and pushes all three image targets in a single build command
- Tags each image with both the version and
:latest
Makefile Targets
| Target | Description |
|---|---|
build-base |
Build the base image |
build-dev |
Build the dev image |
build-ci |
Build the ci image |
push-all |
Build all images and push to registry |
build-all |
Build all three images (no push) |
Variables: ROC_VERSION (default 0.0.0-alpha2), REGISTRY (default git.roo.lol/jbrechtel).
Security Considerations
- Images run as non-root
rocuser (UID 1000) debian:bookworm-slimbase receives regular security patches- Only
ca-certificatesand essential packages are added beyond the binary - The base image has no shell or package manager in the final stage
- Dev image has a shell (bash) by design for interactive use