commit c3e9e2b40b4fa2054f2c308937d60447dd86a8cc Author: Jeena Date: Tue Jan 13 13:48:49 2026 +0900 Initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..802ed5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM archlinux:latest + +# Build args for user +ARG USERNAME=dev +ARG UID=1000 +ARG GID=1000 + +# Install basic tools +RUN pacman -Syu --noconfirm \ + git \ + ca-certificates \ + curl \ + bash \ + && pacman -Scc --noconfirm + +# Create user +RUN groupadd -g ${GID} ${USERNAME} && \ + useradd -m -u ${UID} -g ${GID} -s /bin/bash ${USERNAME} + +# Switch to non-root user +USER ${USERNAME} +WORKDIR /home/${USERNAME} + +# Install OpenCode CLI via official installer +RUN curl -fsSL https://opencode.ai/install | bash + +# Add OpenCode CLI to PATH +ENV PATH="/home/${USERNAME}/.opencode/bin:${PATH}" + +# Default working directory +WORKDIR /home/${USERNAME} diff --git a/README.md b/README.md new file mode 100644 index 0000000..b89f557 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# opencode-container + +Run OpenCode inside an Arch Linux Docker container that closely mirrors a +local development environment, while limiting access to sensitive files on +the host. + +## Features + +- Arch Linux–based image +- Runs as the host user (same username, UID, GID) +- Mounts only the current project directory (same absolute path inside container) +- Persists OpenCode state via XDG directories +- No access to SSH keys, passwords, or full `$HOME` +- Simple shell function (`opencode`) to launch interactively + +## Install + +Change to your projects directory and clone the repository: + +``` +cd ~/Projects/ +git clone https://git.jeena.net/jeena/opencode-container.git +``` +Source the helper file `opencode.aliases` in your shell configuration +(`.bashrc` or `.zshrc`) so the `opencode` function is available in new sessions. + +## Usage + +From any project directory: + +``` +opencode +``` + +The image is built automatically on first use if it does not already exist. +OpenCode starts inside the container with the current directory mounted and +set as the working directory. diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..415106f --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,38 @@ +services: + opencode: + image: opencode-arch + build: + context: . + dockerfile: Dockerfile + args: + USERNAME: "${USER}" + UID: "${UID}" + GID: "${GID}" + + user: "${UID}:${GID}" + working_dir: "${PWD}" + stdin_open: true + tty: true + + environment: + XDG_DATA_HOME: "${XDG_DATA_HOME}" + XDG_CONFIG_HOME: "${XDG_CONFIG_HOME}" + XDG_STATE_HOME: "${XDG_STATE_HOME}" + XDG_CACHE_HOME: "${XDG_CACHE_HOME}" + UID: "${UID}" + GID: "${GID}" + + volumes: + # Current project (read–write) + - "${PWD}:${PWD}" + + # OpenCode persistence (host directories, writable) + - "${XDG_DATA_HOME}/opencode:${XDG_DATA_HOME}/opencode" + - "${XDG_CONFIG_HOME}/opencode:${XDG_CONFIG_HOME}/opencode" + - "${XDG_STATE_HOME}/opencode:${XDG_STATE_HOME}/opencode" + - "${XDG_CACHE_HOME}/opencode:${XDG_CACHE_HOME}/opencode" + + cap_drop: + - ALL + security_opt: + - no-new-privileges:true diff --git a/opencode.aliases b/opencode.aliases new file mode 100644 index 0000000..48d5743 --- /dev/null +++ b/opencode.aliases @@ -0,0 +1,23 @@ +OPENCODE_CONTAINER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" + +opencode() { + # Set defaults if not already defined + : "${XDG_DATA_HOME:=$HOME/.local/share}" + : "${XDG_CONFIG_HOME:=$HOME/.config}" + : "${XDG_STATE_HOME:=$HOME/.local/state}" + : "${XDG_CACHE_HOME:=$HOME/.cache}" + + UID=$(id -u) \ + GID=$(id -g) \ + USER=$(whoami) \ + XDG_DATA_HOME="$XDG_DATA_HOME" \ + XDG_CONFIG_HOME="$XDG_CONFIG_HOME" \ + XDG_STATE_HOME="$XDG_STATE_HOME" \ + XDG_CACHE_HOME="$XDG_CACHE_HOME" \ + docker compose \ + -f "$OPENCODE_CONTAINER_DIR/docker-compose.yaml" \ + run --rm \ + -u "$UID:$GID" \ + opencode bash -c "/home/$USER/.opencode/bin/opencode \"$@\"" \ + 2> >(grep -v "No services to build" >&2) +}