Compare commits

...

4 Commits

4 changed files with 139 additions and 57 deletions
+90 -43
View File
@@ -46,25 +46,21 @@ docker run -d --name devbox \
joakimp/opencode-devbox:latest sleep infinity joakimp/opencode-devbox:latest sleep infinity
# Shell 1: run opencode # Shell 1: run opencode
docker exec -it devbox opencode docker exec -it -u developer devbox opencode
# Shell 2 (separate terminal): aws, git, etc. # Shell 2 (separate terminal): aws, git, etc.
docker exec -it devbox bash docker exec -it -u developer devbox bash
# When done # When done
docker rm -f devbox docker rm -f devbox
``` ```
With docker-compose this is simpler: > **Note:** Always use `-u developer` with `docker exec` — the container starts as root for UID adjustment, then drops to `developer`. Without `-u developer`, exec runs as root.
```bash
docker compose up -d
docker compose exec devbox opencode # terminal 1
docker compose exec devbox bash # terminal 2
```
## Environment Variables ## Environment Variables
All configuration is done via environment variables, typically stored in a `.env` file.
### Provider Configuration ### Provider Configuration
| Variable | Description | Default | | Variable | Description | Default |
@@ -87,14 +83,7 @@ Set the key matching your provider:
| Variable | Description | Default | | Variable | Description | Default |
|---|---|---| |---|---|---|
| `AWS_REGION` | AWS region | `us-east-1` | | `AWS_REGION` | AWS region | `us-east-1` |
| `AWS_PROFILE` | AWS profile name | `default` | | `AWS_PROFILE` | AWS SSO profile name | `default` |
For SSO authentication, start with `bash` and run:
```bash
aws sso login --sso-session <your-session> --use-device-code
opencode
```
### Git ### Git
@@ -114,14 +103,66 @@ The entrypoint automatically detects the owner of `/workspace` and adjusts the c
| `USER_UID` | Container user UID | Auto-detect from `/workspace` owner | | `USER_UID` | Container user UID | Auto-detect from `/workspace` owner |
| `USER_GID` | Container user GID | Auto-detect from `/workspace` owner | | `USER_GID` | Container user GID | Auto-detect from `/workspace` owner |
## Initial Setup
### 1. Create a project directory
```bash ```bash
docker run -it --rm \ mkdir -p ~/projects
-e USER_UID=$(id -u) \
-e USER_GID=$(id -g) \
-v ~/projects:/workspace \
joakimp/opencode-devbox:latest
``` ```
### 2. Create a `.env` file
Create a `.env` file with your configuration. Examples for each provider:
**Anthropic:**
```bash
OPENCODE_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
```
**OpenAI:**
```bash
OPENCODE_PROVIDER=openai
OPENAI_API_KEY=sk-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
```
**AWS Bedrock (SSO):**
```bash
OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/anthropic.claude-sonnet-4-5-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com
```
### 3. AWS SSO setup (Bedrock users only)
AWS SSO requires a `~/.aws/config` file on the host with your SSO session configuration. If you already have this on another machine, copy it:
```bash
scp -r user@other-machine:~/.aws ~/.aws
```
Or configure from scratch:
```bash
aws configure sso
```
You'll be prompted for:
- SSO session name
- SSO start URL
- SSO region
- Registration scopes (typically `sso:account:access`)
The `~/.aws` directory must be mounted into the container (see docker-compose example below).
## Data Storage and Persistence ## Data Storage and Persistence
Understanding what survives container restarts and what doesn't: Understanding what survives container restarts and what doesn't:
@@ -130,27 +171,16 @@ Understanding what survives container restarts and what doesn't:
|---|---|---|---| |---|---|---|---|
| `/workspace` | Host bind mount | ✅ Yes — lives on host | Your project files | | `/workspace` | Host bind mount | ✅ Yes — lives on host | Your project files |
| `/home/developer/.ssh` | Host bind mount (ro) | ✅ Yes — lives on host | SSH keys | | `/home/developer/.ssh` | Host bind mount (ro) | ✅ Yes — lives on host | SSH keys |
| `/home/developer/.aws` | Host bind mount | ✅ Yes — lives on host | AWS credentials/SSO cache |
| `/home/developer/.local/share/opencode` | Named volume (if configured) | ✅ Yes — Docker volume | Session history, memory, auth tokens | | `/home/developer/.local/share/opencode` | Named volume (if configured) | ✅ Yes — Docker volume | Session history, memory, auth tokens |
| `/home/developer/.config/opencode/opencode.json` | Generated by entrypoint | ❌ No — regenerated each start | Provider config, MCP server definitions | | `/home/developer/.config/opencode/opencode.json` | Generated by entrypoint | ❌ No — regenerated each start | Provider config, MCP server definitions |
| `/home/developer/.aws` | Host bind mount (if configured) | ✅ Yes — lives on host | AWS credentials/SSO cache |
### Key points ### Key points
- **Project files** (`/workspace`) are always safe — they're your host filesystem. - **Project files** (`/workspace`) are always safe — they're your host filesystem.
- **opencode config** is auto-generated from `OPENCODE_PROVIDER` env var on each start. It only sets provider and model — no MCP servers. To persist MCP server config, mount your own config file (see Custom opencode Config below). - **opencode config** is auto-generated from `OPENCODE_PROVIDER` env var on each start. It only sets provider and model — no MCP servers. To persist MCP server config, mount your own config file (see Custom opencode Config below).
- **opencode data** (session history, memory) is lost with `--rm` unless you add a named volume. - **opencode data** (session history, memory) is lost with `--rm` unless you add a named volume.
- **AWS SSO tokens** are stored inside the container and lost on restart. Re-run `aws sso login` after restarting. - **AWS SSO tokens** persist across restarts when `~/.aws` is mounted (recommended for Bedrock users).
### Persisting opencode data
Add a named volume to keep session history and memory between runs:
```bash
docker run -it --rm \
-v opencode-data:/home/developer/.local/share/opencode \
... \
joakimp/opencode-devbox:latest
```
## Custom opencode Config ## Custom opencode Config
@@ -167,16 +197,19 @@ When a config file is mounted, the `OPENCODE_PROVIDER` auto-config is skipped.
## Using docker-compose ## Using docker-compose
Create a `docker-compose.yml` and a `.env` file in the same directory: Create a directory with a `docker-compose.yml` and a `.env` file:
```bash ```bash
mkdir opencode-devbox && cd opencode-devbox mkdir opencode-devbox && cd opencode-devbox
``` ```
`.env` — your secrets and settings (never commit this): `.env` — your settings (never commit this):
```bash ```bash
ANTHROPIC_API_KEY=sk-ant-... OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/anthropic.claude-sonnet-4-5-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com GIT_USER_EMAIL=you@example.com
``` ```
@@ -189,16 +222,16 @@ services:
image: joakimp/opencode-devbox:latest image: joakimp/opencode-devbox:latest
stdin_open: true stdin_open: true
tty: true tty: true
env_file:
- .env
environment: environment:
- TERM=xterm-256color - TERM=xterm-256color
- OPENCODE_PROVIDER=anthropic
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- GIT_USER_NAME=${GIT_USER_NAME}
- GIT_USER_EMAIL=${GIT_USER_EMAIL}
volumes: volumes:
- ~/projects:/workspace - ~/projects:/workspace
- ~/.ssh:/home/developer/.ssh:ro - ~/.ssh:/home/developer/.ssh:ro
- devbox-data:/home/developer/.local/share/opencode - devbox-data:/home/developer/.local/share/opencode
# Mount AWS config for Bedrock SSO (required for amazon-bedrock provider)
# - ~/.aws:/home/developer/.aws
# Optional: mount your own opencode config (MCP servers, custom models, etc.) # Optional: mount your own opencode config (MCP servers, custom models, etc.)
# - ./opencode.json:/home/developer/.config/opencode/opencode.json:ro # - ./opencode.json:/home/developer/.config/opencode/opencode.json:ro
# Optional: mount opencode skills from host # Optional: mount opencode skills from host
@@ -209,11 +242,25 @@ volumes:
devbox-data: devbox-data:
``` ```
Docker Compose automatically loads `.env` from the same directory as the compose file. The `${VAR}` references are substituted with values from `.env`. 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.
Then: Then:
```bash ```bash
# Start in background
docker compose up -d
# Open a shell (always use -u developer with exec)
docker compose exec -u developer devbox bash
# For Bedrock: authenticate, then start opencode
aws sso login --sso-session <your-session> --use-device-code
opencode
# Or run opencode directly (if no SSO needed)
docker compose exec -u developer devbox opencode
# One-shot mode (creates and removes container)
docker compose run --rm devbox # direct to opencode docker compose run --rm devbox # direct to opencode
docker compose run --rm devbox bash # interactive shell docker compose run --rm devbox bash # interactive shell
``` ```
+7 -1
View File
@@ -31,13 +31,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
less \ less \
vim-tiny \ vim-tiny \
sudo \ sudo \
gosu \
locales \ locales \
procps \ procps \
unzip \ unzip \
&& ln -s /usr/bin/fdfind /usr/local/bin/fd \ && ln -s /usr/bin/fdfind /usr/local/bin/fd \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# ── gosu (install from GitHub for current Go version, avoids CVEs in Debian package)
ARG GOSU_VERSION=1.17
RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "amd64" ;; arm64) echo "arm64" ;; *) echo "amd64" ;; esac) && \
curl -fsSL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${ARCH}" -o /usr/local/bin/gosu && \
chmod +x /usr/local/bin/gosu && \
gosu --version
# Set locale # Set locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG=en_US.UTF-8 ENV LANG=en_US.UTF-8
+39 -10
View File
@@ -76,10 +76,10 @@ docker compose run --rm devbox
docker compose up -d docker compose up -d
# Attach a shell to the running container # Attach a shell to the running container
docker compose exec devbox bash docker compose exec -u developer devbox bash
# Or run a single command inside it # Or run a single command inside it
docker compose exec devbox aws --version docker compose exec -u developer devbox aws --version
``` ```
> `run` creates a new container (cleaned up with `--rm`). `exec` attaches to an already running one. > `run` creates a new container (cleaned up with `--rm`). `exec` attaches to an already running one.
@@ -95,6 +95,7 @@ docker compose exec devbox aws --version
| `ANTHROPIC_API_KEY` | Anthropic API key | — | | `ANTHROPIC_API_KEY` | Anthropic API key | — |
| `OPENAI_API_KEY` | OpenAI API key | — | | `OPENAI_API_KEY` | OpenAI API key | — |
| `AWS_REGION` | AWS region for Bedrock | `us-east-1` | | `AWS_REGION` | AWS region for Bedrock | `us-east-1` |
| `AWS_PROFILE` | AWS SSO profile name | `default` |
| `GIT_USER_NAME` | Git commit author name | — | | `GIT_USER_NAME` | Git commit author name | — |
| `GIT_USER_EMAIL` | Git commit author email | — | | `GIT_USER_EMAIL` | Git commit author email | — |
| `WORKSPACE_PATH` | Host path to mount | `.` | | `WORKSPACE_PATH` | Host path to mount | `.` |
@@ -150,11 +151,40 @@ docker compose build --build-arg OPENCODE_VERSION=1.5.0
## AWS Bedrock Authentication ## AWS Bedrock Authentication
When using AWS Bedrock as your LLM provider, you need to authenticate via AWS SSO from inside the container. Since the container runs headless (no browser), use the device-code flow: When using AWS Bedrock as your LLM provider, you need:
### 1. AWS config on the host
The container needs access to your `~/.aws/config` with SSO session configuration. If you already have this on another machine, copy it:
```bash ```bash
# Start the container interactively scp -r user@other-machine:~/.aws ~/.aws
docker compose run --rm devbox bash ```
Or configure from scratch on the host:
```bash
aws configure sso
```
### 2. Mount `~/.aws` into the container
Uncomment the AWS volume mount in `docker-compose.yml`:
```yaml
- ~/.aws:/home/developer/.aws
```
Note: do **not** use `:ro` — SSO writes token cache files to this directory.
### 3. Authenticate inside the container
Since the container runs headless (no browser), use the device-code flow:
```bash
# Start the container
docker compose up -d
docker compose exec -u developer devbox bash
# Authenticate — prints a URL and code you open in your local browser # Authenticate — prints a URL and code you open in your local browser
aws sso login --sso-session <your-sso-session> --use-device-code aws sso login --sso-session <your-sso-session> --use-device-code
@@ -165,7 +195,7 @@ opencode
The `--use-device-code` flag outputs a URL and short code instead of trying to open a browser. Copy the URL into any browser (on your laptop, phone, etc.), enter the code, and complete the 2FA flow. The CLI in the container picks up the session automatically. The `--use-device-code` flag outputs a URL and short code instead of trying to open a browser. Copy the URL into any browser (on your laptop, phone, etc.), enter the code, and complete the 2FA flow. The CLI in the container picks up the session automatically.
SSO sessions typically last 812 hours before requiring re-authentication. SSO sessions typically last 812 hours before requiring re-authentication. Since `~/.aws` is mounted from the host, tokens persist across container restarts.
## Secret Scanning ## Secret Scanning
@@ -201,6 +231,7 @@ Allowlisted paths and rules are in `.gitleaks.toml`. The defaults extend gitleak
Host Machine Host Machine
├── ~/projects/my-app ──bind mount──▶ /workspace (container) ├── ~/projects/my-app ──bind mount──▶ /workspace (container)
├── ~/.ssh ──bind mount──▶ /home/developer/.ssh (ro) ├── ~/.ssh ──bind mount──▶ /home/developer/.ssh (ro)
├── ~/.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 bookworm)
@@ -208,7 +239,7 @@ Container (Debian bookworm)
├── AWS CLI v2 (SSO + Bedrock auth) ├── AWS CLI v2 (SSO + Bedrock auth)
├── git, ssh, ripgrep, fd, jq, curl, fzf ├── git, ssh, ripgrep, fd, jq, curl, fzf
├── Node.js (for MCP servers) ├── Node.js (for MCP servers)
├── entrypoint.sh (SSH perms, git config, provider setup) ├── entrypoint.sh (UID adjustment, git config, provider setup)
└── /workspace ← your code lives here └── /workspace ← your code lives here
``` ```
@@ -218,14 +249,12 @@ Container (Debian bookworm)
|---|---|---|---| |---|---|---|---|
| `/workspace` | Host bind mount | ✅ Yes | Your project files | | `/workspace` | Host bind mount | ✅ Yes | Your project files |
| `/home/developer/.ssh` | Host bind mount (ro) | ✅ Yes | SSH keys | | `/home/developer/.ssh` | Host bind mount (ro) | ✅ Yes | SSH keys |
| `/home/developer/.aws` | Host bind mount (if configured) | ✅ Yes | AWS credentials/SSO cache |
| `/home/developer/.local/share/opencode` | Named volume `devbox-data` | ✅ Yes | Session history, memory | | `/home/developer/.local/share/opencode` | Named volume `devbox-data` | ✅ Yes | Session history, memory |
| `/home/developer/.config/opencode/opencode.json` | Generated by entrypoint | ❌ No | Provider/model config | | `/home/developer/.config/opencode/opencode.json` | Generated by entrypoint | ❌ No | Provider/model config |
| `/home/developer/.aws` | Not mounted by default | ❌ No | AWS SSO tokens |
**opencode config** (`opencode.json`) is auto-generated from `OPENCODE_PROVIDER` on each start. It sets provider and model only — no MCP servers. To use MCP servers or custom settings, mount your own config file (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 use MCP servers or custom settings, mount your own config file (see Custom opencode config above).
To persist AWS SSO sessions across restarts, uncomment the `~/.aws` volume mount in `docker-compose.yml`.
## License ## License
MIT MIT
+3 -3
View File
@@ -3,7 +3,7 @@
# Usage: # Usage:
# cp .env.example .env # configure your provider and keys # cp .env.example .env # configure your provider and keys
# docker compose up -d # docker compose up -d
# docker compose exec devbox opencode # docker compose exec -u developer devbox opencode
# #
# Or for interactive one-shot: # Or for interactive one-shot:
# docker compose run --rm devbox # docker compose run --rm devbox
@@ -40,8 +40,8 @@ services:
# Optional: persist opencode data (auth, memory, etc.) # Optional: persist opencode data (auth, memory, etc.)
- devbox-data:/home/developer/.local/share/opencode - devbox-data:/home/developer/.local/share/opencode
# Optional: AWS credentials for Bedrock # Optional: AWS credentials/SSO config (not read-only — SSO writes token cache)
# - ~/.aws:/home/developer/.aws:ro # - ~/.aws:/home/developer/.aws
volumes: volumes:
devbox-data: devbox-data: