Compare commits

..

No commits in common. "a56da84b7a3d58cc0587cd567eb10cb3191a3f33" and "fc2e5b1bca71dcacc237fc236c18da7a279d50bf" have entirely different histories.

5 changed files with 11 additions and 65 deletions

2
.gitignore vendored
View file

@ -0,0 +1,2 @@
container-home/*
!container-home/.gitkeep

View file

@ -9,7 +9,7 @@ the host.
- Arch Linuxbased image
- Runs as the host user (same username, UID, GID)
- Mounts only the current project directory (same absolute path inside container)
- Persists OpenCode state in XDG_DATA_HOME/opencode-container/container-home directory
- Persists OpenCode state in ./container-home directory
- No access to SSH keys, passwords, or full `$HOME`
- Simple shell function (`opencode`) to launch interactively
@ -24,14 +24,10 @@ 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.
We set up the XDG_DATA_HOME/opencode-container/container-home directory as a central $HOME inside of the
We set up the ./container-home directory as a central $HOME inside of the
container, independent of the session or project directory we start in. This
persists the whole $HOME from inside the container so everything OpenCode
writes into config files, etc. persists there.
## Environment Variables
- `XDG_DATA_HOME`: Override default data directory (default: ~/.local/share)
presists the whole $HOME from inside the container so everything opencode
writes into config files, etc. presists there.
## Usage

0
container-home/.gitkeep Normal file
View file

View file

@ -1,22 +0,0 @@
#!/bin/bash
# opencode-container-cleanup.sh - Complete cleanup script for OpenCode container
set -e
# Stop and remove all opencode containers
echo "Stopping and removing opencode containers..."
docker ps -q --filter "name=oc-" | xargs -r docker stop
docker ps -a -q --filter "name=oc-" | xargs -r docker rm -f
# Remove the Docker image
echo "Removing opencode-container image..."
docker rmi opencode-container:latest 2>/dev/null || true
# Remove entire opencode-container directory
CONTAINER_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/opencode-container"
if [ -d "$CONTAINER_DIR" ]; then
echo "Removing ~/.local/share/opencode-container directory..."
rm -rf "$CONTAINER_DIR"
fi
echo "Complete cleanup finished!"

View file

@ -16,43 +16,14 @@ class OpenCodeContainer:
def __init__(self):
self.project_path = Path.cwd().resolve()
self.project_id = self._project_id(self.project_path)
# Store host user info once
self.host_username = os.environ.get('USER', 'dev')
self.host_uid = os.getuid()
self.host_gid = os.getgid()
self.container_name = f"oc-{self.project_path.name}-{self.project_id}"
self.docker_context_dir = Path(__file__).resolve().parent
def _get_xdg_data_home(self) -> Path:
"""Get XDG_DATA_HOME with fallback to ~/.local/share"""
xdg_data = os.environ.get('XDG_DATA_HOME')
if xdg_data:
return Path(xdg_data)
return Path.home() / '.local' / 'share'
@property
def container_home_path(self) -> Path:
"""Container home directory in XDG_DATA_HOME"""
return self._get_xdg_data_home() / 'opencode-container' / 'container-home'
# =========================
# Public entrypoint
# =========================
def run(self, args: list[str]) -> None:
# Ensure container home directory exists
self.container_home_path.mkdir(parents=True, exist_ok=True)
# Pre-create project directory structure to prevent root-owned directories
try:
relative_path = self.project_path.relative_to(Path.home())
(self.container_home_path / relative_path).mkdir(parents=True, exist_ok=True)
except ValueError:
# Project is outside home directory - no action needed
pass
if not self.image_exists():
self.build_image()
@ -83,12 +54,9 @@ class OpenCodeContainer:
).returncode == 0
def build_image(self) -> None:
print(f"Building image '{self.IMAGE}' with user {self.host_username} ({self.host_uid}:{self.host_gid})")
print(f"Building image '{self.IMAGE}'")
self._run([
"docker", "build",
"--build-arg", f"USERNAME={self.host_username}",
"--build-arg", f"UID={self.host_uid}",
"--build-arg", f"GID={self.host_gid}",
"-t", self.IMAGE,
str(self.docker_context_dir),
])
@ -98,14 +66,16 @@ class OpenCodeContainer:
# =========================
def create_container(self) -> None:
uid = os.getuid()
gid = os.getgid()
print(f"Creating container '{self.container_name}'")
self._run([
"docker", "create",
"--name", self.container_name,
"--user", f"{self.host_uid}:{self.host_gid}",
"--user", f"{uid}:{gid}",
"--volume", f"{self.project_path}:{self.project_path}",
"--volume", f"{self.container_home_path}:/home/{self.host_username}",
self.IMAGE,
"sh", "-c", "sleep infinity",
])