Compare commits

...

9 Commits

Author SHA1 Message Date
joakimp 271dc2eb35 Fix Bedrock config: add AWS_PROFILE to generated config, add .agents/skills to volume ownership fix
Publish Docker Image / build-omos (push) Successful in 36m41s
Publish Docker Image / build-base (push) Successful in 38m37s
Publish Docker Image / update-description (push) Successful in 17s
2026-04-13 19:52:08 +02:00
joakimp 875afe0039 Add ~/.local/bin and ~/.cargo/bin to PATH for uv and rustup 2026-04-13 19:48:31 +02:00
joakimp 9e381ebe32 Fix ownership of named volume mount points in entrypoint
Named Docker volumes are created as root on first use, causing permission
denied errors for the developer user. The entrypoint now fixes ownership
of all known volume mount points after UID/GID adjustment.
2026-04-13 19:46:25 +02:00
joakimp 3e048218c3 Update Python example from 3.12 to 3.14 (current stable) 2026-04-13 19:14:33 +02:00
joakimp 6ecd65d18d Update Bedrock model example to eu.anthropic.claude-opus-4-6-v1 2026-04-13 19:04:21 +02:00
joakimp e58962a72c Upgrade base image from Debian bookworm to trixie (current stable)
Publish Docker Image / build-base (push) Successful in 32m39s
Publish Docker Image / build-omos (push) Successful in 39m41s
Publish Docker Image / update-description (push) Successful in 18s
Bookworm (Debian 12) reaches EOL June 2026. Trixie (Debian 13) has been
stable since August 2025 with support until 2028/LTS until 2030.
2026-04-13 13:57:45 +02:00
joakimp d2c0447147 Add VS Code server volume to docker-compose examples and persistence tables 2026-04-13 10:20:25 +02:00
joakimp 77a7daf67f Document VS Code Dev Containers integration for local and remote Docker 2026-04-13 10:14:27 +02:00
joakimp b3cfe641bb Document required host directories to prevent root-owned bind mount issues 2026-04-12 23:52:59 +02:00
6 changed files with 110 additions and 10 deletions
+43 -5
View File
@@ -116,10 +116,22 @@ The entrypoint automatically detects the owner of `/workspace` and adjusts the c
## Initial Setup ## Initial Setup
### 1. Create a project directory ### 1. Create host directories
Bind-mounted directories must exist on the host before starting the container. Docker creates missing directories as root-owned, which causes permission issues.
```bash ```bash
# Required
mkdir -p ~/projects mkdir -p ~/projects
# If mounting opencode config (recommended for persistent settings)
mkdir -p ~/.config/opencode
# If using AWS Bedrock
# mkdir -p ~/.aws
# If mounting neovim config
# mkdir -p ~/.config/nvim
``` ```
### 2. Create a `.env` file ### 2. Create a `.env` file
@@ -145,7 +157,7 @@ GIT_USER_EMAIL=you@example.com
**AWS Bedrock (SSO):** **AWS Bedrock (SSO):**
```bash ```bash
OPENCODE_PROVIDER=amazon-bedrock OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/anthropic.claude-sonnet-4-5-v1 OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1 AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name GIT_USER_NAME=Your Name
@@ -187,6 +199,7 @@ Understanding what survives container restarts and what doesn't:
| `/home/developer/.local/share/uv` | Named volume (if configured) | ✅ Yes — Docker volume | Python installs, uv tool installs | | `/home/developer/.local/share/uv` | Named volume (if configured) | ✅ Yes — Docker volume | Python installs, uv tool installs |
| `/home/developer/.rustup` | Named volume (if configured) | ✅ Yes — Docker volume | Rust toolchains | | `/home/developer/.rustup` | Named volume (if configured) | ✅ Yes — Docker volume | Rust toolchains |
| `/home/developer/.cargo` | Named volume (if configured) | ✅ Yes — Docker volume | Cargo binaries, registry cache | | `/home/developer/.cargo` | Named volume (if configured) | ✅ Yes — Docker volume | Cargo binaries, registry cache |
| `/home/developer/.vscode-server` | Named volume (if configured) | ✅ Yes — Docker volume | VS Code server and extensions |
| `/home/developer/.config/opencode` | Host bind mount (if configured) | ✅ Yes — lives on host | opencode.json, oh-my-opencode-slim.json, skills | | `/home/developer/.config/opencode` | Host bind mount (if configured) | ✅ Yes — lives on host | opencode.json, oh-my-opencode-slim.json, skills |
### Key points ### Key points
@@ -228,7 +241,7 @@ The image includes [uv](https://docs.astral.sh/uv/), a fast Python package manag
```bash ```bash
# Install Python (persists across restarts with devbox-uv volume) # Install Python (persists across restarts with devbox-uv volume)
uv python install 3.12 uv python install 3.14
# Create a virtual environment and install dependencies # Create a virtual environment and install dependencies
uv venv uv venv
@@ -305,6 +318,28 @@ bun run src/index.ts
Node modules are stored in your project directory under `/workspace` and persist automatically. Node modules are stored in your project directory under `/workspace` and persist automatically.
## VS Code Integration
VS Code can connect directly to a running opencode-devbox container for a full IDE experience with IntelliSense, debugging, and extensions running inside the container.
**Requirements:** Install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension. For remote Docker hosts, also install [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh).
**Steps:**
1. Start the container: `docker compose up -d`
2. In VS Code: `Ctrl+Shift+P` → "Dev Containers: Attach to Running Container" → select `opencode-devbox`
For remote Docker hosts (e.g. connecting to a server via SSH), first connect to the remote host with Remote-SSH, then attach to the container from there.
VS Code extensions installed inside the container persist as long as the container exists. For persistent extension storage across container recreations, add a named volume:
```bash
docker run -it --rm \
-v devbox-vscode:/home/developer/.vscode-server \
... \
joakimp/opencode-devbox:latest
```
## Using docker-compose ## Using docker-compose
Create a directory with a `docker-compose.yml` and a `.env` file: Create a directory with a `docker-compose.yml` and a `.env` file:
@@ -317,7 +352,7 @@ mkdir opencode-devbox && cd opencode-devbox
```bash ```bash
OPENCODE_PROVIDER=amazon-bedrock OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/anthropic.claude-sonnet-4-5-v1 OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1 AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name GIT_USER_NAME=Your Name
@@ -347,6 +382,8 @@ services:
# Optional: persist Rust toolchains and cargo data # Optional: persist Rust toolchains and cargo data
# - devbox-rustup:/home/developer/.rustup # - devbox-rustup:/home/developer/.rustup
# - devbox-cargo:/home/developer/.cargo # - devbox-cargo:/home/developer/.cargo
# Optional: persist VS Code server and extensions
# - devbox-vscode:/home/developer/.vscode-server
# Mount AWS config for Bedrock SSO (required for amazon-bedrock provider) # Mount AWS config for Bedrock SSO (required for amazon-bedrock provider)
# - ~/.aws:/home/developer/.aws # - ~/.aws:/home/developer/.aws
# Optional: mount opencode config directory (persists config changes across restarts) # Optional: mount opencode config directory (persists config changes across restarts)
@@ -361,6 +398,7 @@ volumes:
# devbox-uv: # devbox-uv:
# devbox-rustup: # devbox-rustup:
# devbox-cargo: # devbox-cargo:
# devbox-vscode:
``` ```
Docker Compose loads `.env` automatically from the same directory. All variables from `.env` are passed to the container via `env_file`. Do **not** hardcode provider settings in the `environment:` section — use `.env` instead. Docker Compose loads `.env` automatically from the same directory. All variables from `.env` are passed to the container via `env_file`. Do **not** hardcode provider settings in the `environment:` section — use `.env` instead.
@@ -390,7 +428,7 @@ docker compose run --rm devbox bash # interactive shell
### Base image (`latest`) ### Base image (`latest`)
- **Debian bookworm-slim** — glibc, full terminal/PTY support - **Debian trixie-slim** — glibc, full terminal/PTY support
- **opencode** — AI coding assistant - **opencode** — AI coding assistant
- **Node.js 22** — for npx-based MCP servers - **Node.js 22** — for npx-based MCP servers
- **AWS CLI v2** — SSO and Bedrock authentication - **AWS CLI v2** — SSO and Bedrock authentication
+2 -1
View File
@@ -1,7 +1,7 @@
# opencode-devbox — portable AI dev environment # opencode-devbox — portable AI dev environment
# Debian-based container with opencode and configurable dev tools # Debian-based container with opencode and configurable dev tools
ARG DEBIAN_VERSION=bookworm-slim ARG DEBIAN_VERSION=trixie-slim
FROM debian:${DEBIAN_VERSION} AS base FROM debian:${DEBIAN_VERSION} AS base
ARG TARGETARCH ARG TARGETARCH
@@ -113,6 +113,7 @@ ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8
ENV EDITOR=nvim ENV EDITOR=nvim
ENV PATH="/home/developer/.local/bin:/home/developer/.cargo/bin:${PATH}"
# ── Node.js (required for opencode v1.x install + MCP servers) ────── # ── Node.js (required for opencode v1.x install + MCP servers) ──────
ARG NODE_VERSION=22 ARG NODE_VERSION=22
+40 -3
View File
@@ -27,7 +27,7 @@ docker compose run --rm devbox
## Features ## Features
- **Debian bookworm** base — glibc, full PTY/terminal support - **Debian trixie** base — glibc, full PTY/terminal support
- **Configurable providers** — Anthropic, OpenAI, AWS Bedrock via env vars - **Configurable providers** — Anthropic, OpenAI, AWS Bedrock via env vars
- **Host filesystem access** — bind mount any directory as `/workspace` - **Host filesystem access** — bind mount any directory as `/workspace`
- **SSH key forwarding** — git push/pull to private repos - **SSH key forwarding** — git push/pull to private repos
@@ -42,6 +42,18 @@ docker compose run --rm devbox
## Usage ## Usage
### Prerequisites
Bind-mounted directories must exist on the host before starting the container. Docker creates missing directories as root-owned, which causes permission issues.
```bash
# Required: workspace for your projects
mkdir -p ~/projects
# If mounting opencode config (recommended for persistent settings)
mkdir -p ~/.config/opencode
```
### Connecting to the container ### Connecting to the container
From your laptop, SSH into the remote server where Docker is running, then start the container: From your laptop, SSH into the remote server where Docker is running, then start the container:
@@ -145,7 +157,7 @@ The image includes [uv](https://docs.astral.sh/uv/), a fast Python package manag
```bash ```bash
# Install Python (persists across restarts with devbox-uv volume) # Install Python (persists across restarts with devbox-uv volume)
uv python install 3.12 uv python install 3.14
# Create a virtual environment and install dependencies # Create a virtual environment and install dependencies
uv venv uv venv
@@ -228,6 +240,30 @@ bun run src/index.ts
Node modules are stored in your project directory under `/workspace` and persist automatically. Node modules are stored in your project directory under `/workspace` and persist automatically.
### VS Code integration
VS Code can connect directly to a running opencode-devbox container for a full IDE experience with IntelliSense, debugging, and extensions running inside the container.
**Local Docker (Docker running on your workstation):**
1. Install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension
2. Start the container: `docker compose up -d`
3. In VS Code: `Ctrl+Shift+P` → "Dev Containers: Attach to Running Container" → select `opencode-devbox`
**Remote Docker (Docker running on a remote server, e.g. via SSH):**
1. Install the [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) and [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extensions
2. Connect to the remote host: `Ctrl+Shift+P` → "Remote-SSH: Connect to Host"
3. On the remote host, start the container: `docker compose up -d`
4. In VS Code (now connected to the remote): `Ctrl+Shift+P` → "Dev Containers: Attach to Running Container"
VS Code extensions installed inside the container persist as long as the container exists (not removed with `docker compose down`). For persistent extension storage across container recreations, add a named volume:
```yaml
volumes:
- devbox-vscode:/home/developer/.vscode-server
```
### Rebuilding the Image ### Rebuilding the Image
`docker compose run` and `docker compose up` use the existing image — they **do not rebuild** when you change the Dockerfile or build args (e.g. updating `OPENCODE_VERSION`). Rebuild explicitly: `docker compose run` and `docker compose up` use the existing image — they **do not rebuild** when you change the Dockerfile or build args (e.g. updating `OPENCODE_VERSION`). Rebuild explicitly:
@@ -397,7 +433,7 @@ Host Machine
├── ~/.aws ──bind mount──▶ /home/developer/.aws (Bedrock SSO) ├── ~/.aws ──bind mount──▶ /home/developer/.aws (Bedrock SSO)
└── .env ──env vars───▶ provider config + API keys └── .env ──env vars───▶ provider config + API keys
Container (Debian bookworm) Container (Debian trixie)
├── opencode binary ├── opencode binary
├── oh-my-opencode-slim (optional — multi-agent orchestration plugin, includes Bun) ├── oh-my-opencode-slim (optional — multi-agent orchestration plugin, includes Bun)
├── AWS CLI v2 (SSO + Bedrock auth) ├── AWS CLI v2 (SSO + Bedrock auth)
@@ -420,6 +456,7 @@ Container (Debian bookworm)
| `/home/developer/.local/share/uv` | Named volume `devbox-uv` (if configured) | ✅ Yes | Python installs, uv tool installs | | `/home/developer/.local/share/uv` | Named volume `devbox-uv` (if configured) | ✅ Yes | Python installs, uv tool installs |
| `/home/developer/.rustup` | Named volume `devbox-rustup` (if configured) | ✅ Yes | Rust toolchains | | `/home/developer/.rustup` | Named volume `devbox-rustup` (if configured) | ✅ Yes | Rust toolchains |
| `/home/developer/.cargo` | Named volume `devbox-cargo` (if configured) | ✅ Yes | Cargo binaries, registry cache | | `/home/developer/.cargo` | Named volume `devbox-cargo` (if configured) | ✅ Yes | Cargo binaries, registry cache |
| `/home/developer/.vscode-server` | Named volume `devbox-vscode` (if configured) | ✅ Yes | VS Code server and extensions |
| `/home/developer/.config/opencode` | Host bind mount (if configured) | ✅ Yes | opencode.json, oh-my-opencode-slim.json, skills | | `/home/developer/.config/opencode` | Host bind mount (if configured) | ✅ Yes | opencode.json, oh-my-opencode-slim.json, skills |
**opencode config** (`opencode.json`) is auto-generated from `OPENCODE_PROVIDER` on each start. It sets provider and model only — no MCP servers. To persist config changes and use custom settings, mount the config directory from the host (see Custom opencode config above). **opencode config** (`opencode.json`) is auto-generated from `OPENCODE_PROVIDER` on each start. It sets provider and model only — no MCP servers. To persist config changes and use custom settings, mount the config directory from the host (see Custom opencode config above).
+4
View File
@@ -54,6 +54,9 @@ services:
# - devbox-rustup:/home/developer/.rustup # - devbox-rustup:/home/developer/.rustup
# - devbox-cargo:/home/developer/.cargo # - devbox-cargo:/home/developer/.cargo
# Optional: persist VS Code server and extensions across container recreations
# - devbox-vscode:/home/developer/.vscode-server
# Optional: AWS credentials/SSO config (not read-only — SSO writes token cache) # Optional: AWS credentials/SSO config (not read-only — SSO writes token cache)
# - ~/.aws:/home/developer/.aws # - ~/.aws:/home/developer/.aws
@@ -62,3 +65,4 @@ volumes:
devbox-uv: devbox-uv:
# devbox-rustup: # devbox-rustup:
# devbox-cargo: # devbox-cargo:
# devbox-vscode:
+2 -1
View File
@@ -48,7 +48,8 @@ EOF
"provider": { "provider": {
"amazon-bedrock": { "amazon-bedrock": {
"options": { "options": {
"region": "${AWS_REGION:-us-east-1}" "region": "${AWS_REGION:-us-east-1}",
"profile": "${AWS_PROFILE:-default}"
} }
} }
} }
+19
View File
@@ -46,5 +46,24 @@ if [ -d "/home/$USER_NAME/.ssh" ] && [ "$(ls -A "/home/$USER_NAME/.ssh" 2>/dev/n
fi fi
fi fi
# ── Fix ownership of named volume mount points ──────────────────────
# Named volumes are created as root on first use. Fix ownership so the
# developer user can write to them.
FINAL_UID="${TARGET_UID:-$CURRENT_UID}"
FINAL_GID="${TARGET_GID:-$CURRENT_GID}"
for dir in \
/home/"$USER_NAME"/.local/share/opencode \
/home/"$USER_NAME"/.local/share/uv \
/home/"$USER_NAME"/.rustup \
/home/"$USER_NAME"/.cargo \
/home/"$USER_NAME"/.vscode-server \
/home/"$USER_NAME"/.config/opencode \
/home/"$USER_NAME"/.config/nvim \
/home/"$USER_NAME"/.agents/skills; do
if [ -d "$dir" ] && [ "$(stat -c '%u' "$dir" 2>/dev/null)" != "$FINAL_UID" ]; then
chown -R "$FINAL_UID":"$FINAL_GID" "$dir" 2>/dev/null || true
fi
done
# ── Drop to developer user for remaining setup ────────────────────── # ── Drop to developer user for remaining setup ──────────────────────
exec gosu "$USER_NAME" /usr/local/bin/entrypoint-user.sh "$@" exec gosu "$USER_NAME" /usr/local/bin/entrypoint-user.sh "$@"