Compare commits

...

5 Commits

Author SHA1 Message Date
joakimp f08480182a Bump opencode to v1.4.6
Publish Docker Image / build-omos (push) Successful in 1h19m28s
Publish Docker Image / build-base (push) Successful in 1h30m47s
Publish Docker Image / update-description (push) Successful in 13s
2026-04-15 12:21:29 +02:00
joakimp 5ec47fdf4b Add AGENTS.md with project-specific guidance for opencode sessions 2026-04-14 19:28:26 +02:00
joakimp 210cb7d1a1 Document Python 3.13 included by default in Trixie base image 2026-04-14 13:01:49 +02:00
joakimp 0a3e142b8f Document locale and editor override in README and DOCKER_HUB 2026-04-14 08:37:08 +02:00
joakimp 158e1590a6 Generate all UTF-8 locales, allow locale override via env vars
Users can set LANG, LANGUAGE, LC_ALL in .env to override the default
en_US.UTF-8 locale (e.g. sv_SE.UTF-8 for Swedish).
2026-04-14 08:35:42 +02:00
5 changed files with 92 additions and 11 deletions
+5
View File
@@ -31,6 +31,11 @@ WORKSPACE_PATH=~/projects
# Path to SSH keys on host
SSH_KEY_PATH=~/.ssh
# ── Locale (defaults to en_US.UTF-8) ─────────────────────────────────
# LANG=sv_SE.UTF-8
# LANGUAGE=sv_SE:sv
# LC_ALL=sv_SE.UTF-8
# ── oh-my-opencode-slim (multi-agent orchestration) ──────────────────
# Requires image built with INSTALL_OMOS=true
# ENABLE_OMOS=false
+47
View File
@@ -0,0 +1,47 @@
# AGENTS.md
## Project overview
Docker image packaging [opencode](https://opencode.ai) into a production-ready dev container. Two image variants (base and omos) are published to Docker Hub via Gitea Actions CI. Not a library or application — this is infrastructure (Dockerfile, entrypoint scripts, docker-compose, documentation).
## File roles
- `Dockerfile` — single multi-stage build for both variants. OMOS variant is controlled by `INSTALL_OMOS=true` build arg. All GitHub-sourced binaries are pinned with version ARGs.
- `entrypoint.sh` — runs as root: UID/GID adjustment, SSH permissions, volume ownership fixes. Then drops to developer via gosu.
- `entrypoint-user.sh` — runs as developer: git config, opencode.json generation from env vars, OMOS setup.
- `DOCKER_HUB.md` — pushed to Docker Hub description via CI API call. Must stay under 25KB. Short description field must be ≤100 bytes.
- `README.md` — source repo documentation. Must stay in sync with DOCKER_HUB.md (both describe the same features but for different audiences).
- `.gitea/workflows/docker-publish.yml` — CI pipeline: three parallel jobs (build-base, build-omos, update-description). Triggered by tag push only.
## Versioning scheme
Tags follow `v{opencode_version}{letter}` — e.g. `v1.4.3k`. The number matches the opencode npm version. The letter suffix increments for container-level changes (tooling, docs, CVE fixes) on the same opencode version. CI produces four Docker Hub tags per release: `vX.Y.Zn`, `latest`, `vX.Y.Zn-omos`, `latest-omos`.
## Critical conventions
- **entrypoint.sh volume ownership loop** — when adding a new named volume mount point, add it to the `for dir in ...` loop in `entrypoint.sh` so root-owned volumes get chowned on startup.
- **Three docs to keep in sync** — Dockerfile changes that add tools or features must be reflected in `README.md`, `DOCKER_HUB.md`, and `.env.example`. The docker-compose examples in both docs must match the source `docker-compose.yml` pattern.
- **GitHub-sourced binaries** — fzf, gosu, git-lfs, neovim, bat, eza, zoxide, uv, rustup are installed from upstream releases (not apt) with pinned versions. Use the same `ARCH` case-switch pattern for multi-arch support (amd64/arm64).
- **Shell scripts use `set -euo pipefail`** — both entrypoints are strict. Errors in volume chown or SSH permission operations are intentionally suppressed with `|| true`.
- **Docker Hub description update** — uses `/v2/auth/token` endpoint (not the deprecated `/v2/users/login`). Auth uses `identifier`/`secret` fields, returns `access_token`, sent as `Bearer`. Short description must be ≤100 bytes.
## CI quirks
- Both build jobs include an IPv4 preference step (`gai.conf` + `driver-opts: network=host` for buildx) to work around intermittent IPv6 failures on the Gitea runners.
- `update-description` job runs only when both builds succeed (`needs: [build-base, build-omos]`).
- Tags must be pushed to trigger CI. Pushing to `main` alone does not build images.
## Testing changes
No test suite. Verify by:
1. Building locally: `docker compose build`
2. Running: `docker compose run --rm devbox bash`
3. Checking tool availability inside container: `nvim --version`, `bat --version`, `uv --version`, etc.
4. For entrypoint changes: test with a non-1000 UID workspace to verify UID adjustment and volume ownership fixes.
## Commit style
Imperative mood, first line summarizes the change. Multi-line body explains "why" when non-obvious. Examples from history:
- `Fix ownership of named volume mount points in entrypoint`
- `Add uv package manager to base image for on-demand Python support`
- `Upgrade base image from Debian bookworm to trixie (current stable)`
+26 -4
View File
@@ -114,6 +114,25 @@ The entrypoint automatically detects the owner of `/workspace` and adjusts the c
| `USER_UID` | Container user UID | Auto-detect from `/workspace` owner |
| `USER_GID` | Container user GID | Auto-detect from `/workspace` owner |
### Locale and Editor
The container defaults to English (`en_US.UTF-8`) and neovim as the editor. Override via environment variables:
| Variable | Description | Default |
|---|---|---|
| `LANG` | System locale | `en_US.UTF-8` |
| `LANGUAGE` | Language priority list | `en_US:en` |
| `LC_ALL` | Override all locale settings | `en_US.UTF-8` |
| `EDITOR` | Default text editor | `nvim` |
All common UTF-8 locales are pre-generated in the image. Example for Swedish:
```bash
LANG=sv_SE.UTF-8
LANGUAGE=sv_SE:sv
LC_ALL=sv_SE.UTF-8
```
## Initial Setup
### 1. Create host directories
@@ -237,13 +256,13 @@ docker run -it --rm \
## Python Development with uv
The image includes [uv](https://docs.astral.sh/uv/), a fast Python package manager that replaces pip, venv, and pyenv. Python is not pre-installed but can be installed on demand:
The image includes Python 3.13 (from Debian Trixie) and [uv](https://docs.astral.sh/uv/), a fast Python package manager that replaces pip, venv, and pyenv:
```bash
# Install Python (persists across restarts with devbox-uv volume)
uv python install 3.14
# Python 3.13 is available out of the box
python3 --version
# Create a virtual environment and install dependencies
# Use uv for package management
uv venv
uv pip install -r requirements.txt
@@ -255,6 +274,9 @@ uv run python script.py
# Install standalone Python tools
uvx ruff check .
# Install a newer Python version (persists with devbox-uv volume)
uv python install 3.14
```
To persist Python installs across container restarts, add a named volume:
+3 -3
View File
@@ -5,7 +5,7 @@ ARG DEBIAN_VERSION=trixie-slim
FROM debian:${DEBIAN_VERSION} AS base
ARG TARGETARCH
ARG OPENCODE_VERSION=1.4.3
ARG OPENCODE_VERSION=1.4.6
LABEL maintainer="joakimp"
LABEL description="Portable opencode developer container"
@@ -107,8 +107,8 @@ RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "x86_64" ;; arm64) echo "aarch64"
curl -fsSL "https://static.rust-lang.org/rustup/dist/${ARCH}-unknown-linux-gnu/rustup-init" -o /usr/local/bin/rustup-init && \
chmod +x /usr/local/bin/rustup-init
# Set locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
# Set locale — generate common UTF-8 locales (override via LANG/LC_ALL env vars)
RUN sed -i '/\.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
+11 -4
View File
@@ -117,6 +117,10 @@ docker compose exec -u developer devbox aws --version
| `SSH_KEY_PATH` | Host SSH key directory | `~/.ssh` |
| `USER_UID` | Override container user UID | Auto-detect from `/workspace` |
| `USER_GID` | Override container user GID | Auto-detect from `/workspace` |
| `LANG` | System locale | `en_US.UTF-8` |
| `LANGUAGE` | Language priority list | `en_US:en` |
| `LC_ALL` | Override all locale settings | `en_US.UTF-8` |
| `EDITOR` | Default text editor | `nvim` |
| `ENABLE_OMOS` | Enable oh-my-opencode-slim multi-agent orchestration | `false` |
| `OMOS_TMUX` | Enable tmux pane integration for OMOS | `false` |
| `OMOS_SKILLS` | Install OMOS recommended skills on first run | `true` |
@@ -153,13 +157,13 @@ volumes:
### Python development with uv
The image includes [uv](https://docs.astral.sh/uv/), a fast Python package manager that replaces pip, venv, and pyenv. Python is not pre-installed but can be installed on demand:
The image includes Python 3.13 (from Debian Trixie) and [uv](https://docs.astral.sh/uv/), a fast Python package manager that replaces pip, venv, and pyenv:
```bash
# Install Python (persists across restarts with devbox-uv volume)
uv python install 3.14
# Python 3.13 is available out of the box
python3 --version
# Create a virtual environment and install dependencies
# Use uv for package management
uv venv
uv pip install -r requirements.txt
@@ -171,6 +175,9 @@ uv run python script.py
# Install standalone Python tools
uvx ruff check .
# Install a newer Python version (persists with devbox-uv volume)
uv python install 3.14
```
Python installations are stored in `~/.local/share/uv/`. To persist them across container restarts, add the `devbox-uv` named volume to your `docker-compose.yml`: