chore: add OCI image design spec for Roc compiler/dev environment
This commit is contained in:
@@ -0,0 +1,170 @@
|
|||||||
|
# Roc Language OCI Images
|
||||||
|
|
||||||
|
**Date:** 2026-06-04
|
||||||
|
**Status:** Design — approved
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Build and publish OCI container images for the [Roc language](https://roc-lang.org/) 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 file
|
||||||
|
- `ca-certificates` (build-time only, removed from final layer)
|
||||||
|
- `roc` user/group (UID 1000)
|
||||||
|
- `PATH` includes `/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:**
|
||||||
|
```bash
|
||||||
|
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:**
|
||||||
|
```yaml
|
||||||
|
- run: docker run --rm git.roo.lol/jbrechtel/roc-tools-ci roc build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Release Download Strategy
|
||||||
|
|
||||||
|
The `scripts/download-roc.sh` script:
|
||||||
|
|
||||||
|
1. Accepts `ROC_VERSION` and `TARGETARCH` arguments
|
||||||
|
2. Constructs the GitHub release URL:
|
||||||
|
```
|
||||||
|
https://github.com/roc-lang/roc/releases/download/{ROC_VERSION}/roc-linux_{ARCH}-{ROC_VERSION}.tar.gz
|
||||||
|
```
|
||||||
|
Where `ARCH` is `x86_64` (for amd64) or `aarch64` (for arm64).
|
||||||
|
3. Downloads and extracts the tarball
|
||||||
|
4. Copies the `roc` and `roc_language_server` binaries to `/opt/roc/bin/`
|
||||||
|
5. Copies `lib/wasi-libc.a` to `/opt/roc/lib/`
|
||||||
|
6. Copies `LICENSE` to `/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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
1. Extracts the Roc version from the tag (`v0.0.0-alpha2` → `0.0.0-alpha2`)
|
||||||
|
2. Sets up Docker Buildx with multi-arch support (linux/amd64, linux/arm64)
|
||||||
|
3. Logs into the Gitea container registry using the Gitea Actions token
|
||||||
|
4. Builds and pushes all three image targets in a single build command
|
||||||
|
5. 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 `roc` user (UID 1000)
|
||||||
|
- `debian:bookworm-slim` base receives regular security patches
|
||||||
|
- Only `ca-certificates` and 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
|
||||||
Reference in New Issue
Block a user