commit a84835cd7e1922df1e03eb2a5d2fd519e0d19232 Author: openclaw Date: Tue Feb 24 16:58:17 2026 +0000 Initial commit: Claude Dev Container with Java multi-version, Docker CLI, and web terminal diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5533d2f --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# Copy this file to .env and set your own passwords + +# Web terminal credentials +TERMINAL_USER=developer +TERMINAL_PASSWORD=changeme diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7aa3daa --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Environment variables (contains passwords!) +.env + +# Claude credentials (personal/sensitive) +claude-credentials/ + +# Persistent data folders +workspace/ + +# Docker +.DS_Store +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..14ba3df --- /dev/null +++ b/Dockerfile @@ -0,0 +1,104 @@ +FROM ubuntu:22.04 + +# Prevent interactive prompts during installation +ENV DEBIAN_FRONTEND=noninteractive + +# Set up user and workspace +ENV USER=developer +ENV HOME=/home/$USER +ENV WORKSPACE=$HOME/workspace +ENV SDKMAN_DIR=$HOME/.sdkman + +# Install base dependencies +RUN apt-get update && apt-get install -y \ + curl \ + wget \ + git \ + build-essential \ + zip \ + unzip \ + software-properties-common \ + ca-certificates \ + gnupg \ + lsb-release \ + sudo \ + nano \ + vim \ + htop \ + net-tools \ + && rm -rf /var/lib/apt/lists/* + +# Create developer user with sudo privileges +RUN useradd -m -s /bin/bash -G sudo $USER && \ + echo "$USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + mkdir -p $WORKSPACE && \ + chown -R $USER:$USER $HOME + +# Switch to developer user +USER $USER +WORKDIR $HOME + +# Install SDKMAN +RUN curl -s "https://get.sdkman.io" | bash + +# Install multiple Java versions via SDKMAN +RUN bash -c "source $SDKMAN_DIR/bin/sdkman-init.sh && \ + sdk install java 11.0.22-tem && \ + sdk install java 17.0.10-tem && \ + sdk install java 21.0.2-tem && \ + sdk install java 25-tem && \ + sdk default java 25-tem" + +# Install Maven and Gradle +RUN bash -c "source $SDKMAN_DIR/bin/sdkman-init.sh && \ + sdk install maven && \ + sdk install gradle" + +# Switch back to root for system-level installations +USER root + +# Install Docker CLI (no daemon - will use host socket) +RUN install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ + chmod a+r /etc/apt/keyrings/docker.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + apt-get update && \ + apt-get install -y docker-ce-cli docker-compose-plugin && \ + usermod -aG docker $USER && \ + rm -rf /var/lib/apt/lists/* + +# Install ttyd (web terminal) +RUN wget https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.x86_64 -O /usr/local/bin/ttyd && \ + chmod +x /usr/local/bin/ttyd + +# Install Node.js (needed for Claude Code CLI) +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ + apt-get install -y nodejs && \ + rm -rf /var/lib/apt/lists/* + +# Switch back to developer user +USER $USER + +# Install Claude Code CLI +RUN npm install -g @anthropic-ai/claude-code + +# Create .claude directory (will be mounted with credentials from Mac) +RUN mkdir -p $HOME/.claude + +# Source SDKMAN in bashrc for interactive shells +RUN echo 'source "$SDKMAN_DIR/bin/sdkman-init.sh"' >> $HOME/.bashrc + +# Create startup script +USER root +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Expose ports +# 7681: ttyd (web terminal) +EXPOSE 7681 + +USER $USER +WORKDIR $WORKSPACE + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7b2e240 --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +.PHONY: help build up down restart logs shell clean + +help: + @echo "Claude Dev Container - Commands" + @echo "" + @echo " make build - Build the Docker image" + @echo " make up - Start the container" + @echo " make down - Stop the container" + @echo " make restart - Restart the container" + @echo " make logs - Show container logs" + @echo " make shell - Open bash shell in container" + @echo " make clean - Remove container and image" + @echo "" + +build: + docker compose build + +up: + docker compose up -d + @echo "" + @echo "Container started!" + @echo " VS Code: http://localhost:8080" + @echo " Web Terminal: http://localhost:7681" + @echo "" + +down: + docker compose down + +restart: + docker compose restart + +logs: + docker compose logs -f + +shell: + docker exec -it claude-dev-container bash + +clean: + docker compose down + docker rmi claude-dev-container-claude-dev || true diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..c2b126b --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,150 @@ +# πŸš€ Quick Start + +## Voorbereiding (BELANGRIJK!) + +### 1. Kopieer Claude credentials van Mac + +**Op je Mac** (waar je al ingelogd bent in Claude Code): + +```bash +# Check of credentials bestaan +ls -la ~/.claude + +# Kopieer naar NAS +scp -r ~/.claude/ admin@[nas-ip]:/docker/claude-dev/claude-credentials +``` + +**Of via Finder**: Cmd+Shift+G β†’ `~/.claude` β†’ Upload naar NAS + +--- + +## Voor Synology + +### 2. Upload naar Synology +Upload deze hele folder naar: `/docker/claude-dev` + +### 3. Check Docker group ID +```bash +ssh admin@[nas-ip] +getent group docker +# Output: docker:x:999:... +``` + +### 4. Pas docker-compose.yml aan (als nodig) +```yaml +group_add: + - "999" # <- Zet hier het juiste nummer uit stap 3 +``` + +### 5. Zet wachtwoorden +```bash +cd /docker/claude-dev +cp .env.example .env +nano .env # Pas TERMINAL_PASSWORD aan +``` + +### 6. Start via Container Manager +- Open Container Manager +- Project β†’ Create +- Selecteer `/docker/claude-dev` +- Start! + +### 7. Open terminal +Browser β†’ `http://[synology-ip]:7681` +Login met credentials uit `.env` + +--- + +## Lokaal testen (Mac/Linux) + +```bash +# Check setup +./check-setup.sh + +# Kopieer je eigen credentials +cp -r ~/.claude ./claude-credentials + +# Setup credentials +cp .env.example .env +nano .env + +# Build en start +make build && make up + +# Of zonder Makefile: +docker compose build +docker compose up -d + +# Open terminal +open http://localhost:7681 +``` + +--- + +## Eerste keer in de container + +```bash +# Check of Claude werkt +claude --version + +# Test authentication +claude "Hello, can you help me?" + +# Check Java versies +sdk list java + +# Test Docker toegang +docker ps + +# Start coding! +claude chat +``` + +## Claude Code commando's + +```bash +# Interactive chat +claude chat + +# One-shot +claude "Maak een Spring Boot REST API" + +# Met context +claude --context pom.xml src/ "add JUnit tests" + +# Model kiezen +claude -m claude-opus-4 "complex vraag" +``` + +## Java versie switchen + +```bash +# Tijdelijk (deze sessie) +sdk use java 17.0.10-tem + +# Permanent +sdk default java 21.0.2-tem +``` + +--- + +## Troubleshooting + +**Claude zegt "not authenticated"**: +```bash +# Check credentials +ls -la ~/.claude +# Als leeg: opnieuw kopiΓ«ren van Mac +``` + +**Terminal vraagt om login maar credentials werken niet**: +- Check `.env` bestand +- Restart container: `docker compose restart` + +**Docker permission denied**: +- Check `group_add` in docker-compose.yml +- Moet matchen met output van `getent group docker` + +--- + +**Klaar! πŸŽ‰** Open `http://[ip]:7681` en begin met `claude chat` diff --git a/README.md b/README.md new file mode 100644 index 0000000..8bf668d --- /dev/null +++ b/README.md @@ -0,0 +1,239 @@ +# Claude Dev Container + +Docker container met Java development environment, Claude Code CLI, web terminal en Docker CLI. + +## Features + +- πŸ”’ **Multiple Java versions** (11, 17, 21, 25) via SDKMAN - makkelijk switchen +- πŸ€– **Claude Code CLI** - AI coding assistant in de terminal +- πŸ–₯️ **Web terminal** (ttyd) met basic authentication +- 🐳 **Docker CLI** - gebruikt host Docker socket (Synology compatible) +- πŸ“¦ **Maven & Gradle** pre-installed +- πŸ” **Password protected** terminal + +## Installatie op Synology + +### 1. Claude credentials voorbereiden (BELANGRIJK!) + +**Op je Mac** waar je al ingelogd bent in Claude Code: + +```bash +# Check of credentials bestaan +ls -la ~/.claude + +# Kopieer naar NAS (pas IP aan) +scp -r ~/.claude/ admin@[nas-ip]:/docker/claude-dev/claude-credentials +``` + +**Of via Finder:** +1. Cmd+Shift+G β†’ typ `~/.claude` +2. Kopieer de hele folder +3. Upload naar NAS via File Station β†’ `/docker/claude-dev/claude-credentials` + +### 2. Bestanden voorbereiden + +Upload deze folder naar je Synology (bijv. via File Station naar `/docker/claude-dev`). + +**Structuur moet zijn:** +``` +/docker/claude-dev/ +β”œβ”€β”€ claude-credentials/ # GekopieΓ«rd van Mac ~/.claude +β”‚ └── session.json # (en andere bestanden) +β”œβ”€β”€ Dockerfile +β”œβ”€β”€ docker-compose.yml +β”œβ”€β”€ entrypoint.sh +└── ... +``` + +### 3. Wachtwoorden instellen + +```bash +cd /docker/claude-dev +cp .env.example .env +nano .env # Pas terminal wachtwoord aan +``` + +### 4. Docker group ID checken (belangrijk!) + +SSH naar je Synology en check de Docker group ID: +```bash +getent group docker +``` + +Je ziet iets als: `docker:x:999:...` + +Als het getal **niet** 999 is, pas het aan in `docker-compose.yml` bij `group_add`. + +### 5. Container starten + +Via **Container Manager**: +1. Open Container Manager +2. Ga naar Project +3. Klik "Create" +4. Selecteer de folder met `docker-compose.yml` +5. Start het project + +**Of via SSH:** +```bash +cd /docker/claude-dev +docker compose up -d +``` + +### 6. Toegang + +**Web Terminal**: `http://[synology-ip]:7681` +- Login: gebruik `TERMINAL_USER` en `TERMINAL_PASSWORD` uit `.env` + +## Claude Code gebruiken + +In de terminal: + +```bash +# Interactive chat +claude chat + +# One-shot commando +claude "Maak een Spring Boot REST API" + +# Met opties +claude -p "Schrijf unit tests" --model claude-opus-4 + +# Hulp +claude --help +``` + +Claude gebruikt automatisch je gemounte credentials uit `~/.claude`. + +## Java versies switchen + +```bash +# Lijst van geΓ―nstalleerde versies +sdk list java + +# Switch voor huidige sessie +sdk use java 17.0.10-tem + +# Zet als default +sdk default java 21.0.2-tem + +# Check huidige versie +java -version +``` + +## Docker gebruiken + +De container gebruikt de Docker socket van je Synology host: + +```bash +# Werkt gewoon +docker ps +docker images +docker run hello-world +docker compose up +``` + +## Workspace persistentie + +Je code wordt opgeslagen in: `./workspace/` + +Deze map is gemount, dus je werk blijft bewaard na container restart. + +## Troubleshooting + +### Claude Code zegt "not authenticated" + +Check of credentials correct gemount zijn: +```bash +# In de container +ls -la ~/.claude +cat ~/.claude/session.json +``` + +Als de folder leeg is: +1. Kopieer opnieuw vanaf Mac: `scp -r ~/.claude admin@[nas]:/docker/claude-dev/claude-credentials` +2. Check permissions: `chmod -R 755 ./claude-credentials` +3. Restart container + +### Docker permission denied + +Check of de `group_add` in `docker-compose.yml` matcht met je Docker group ID: +```bash +getent group docker +``` + +### Container start niet + +Check logs: +```bash +docker logs claude-dev-container +``` + +Of via Container Manager: selecteer container β†’ Details β†’ Log + +### Poort in gebruik + +Pas de poort aan in `docker-compose.yml`: +```yaml +ports: + - "7682:7681" # bijv. 7682 in plaats van 7681 +``` + +## Structuur + +``` +claude-dev-container/ +β”œβ”€β”€ Dockerfile # Container definitie +β”œβ”€β”€ docker-compose.yml # Synology deployment +β”œβ”€β”€ entrypoint.sh # Startup script +β”œβ”€β”€ .env # Wachtwoorden (niet committen!) +β”œβ”€β”€ .env.example # Template voor .env +β”œβ”€β”€ claude-credentials/ # GekopieΓ«rd van Mac ~/.claude (niet committen!) +β”œβ”€β”€ workspace/ # Je code (persistent) +└── README.md # Deze file +``` + +## Custom aanpassingen + +### Meer Java versies toevoegen + +Edit `Dockerfile`, voeg toe in de SDKMAN sectie: +```dockerfile +sdk install java 23-tem && \ +``` + +### Extra tools installeren + +In de `Dockerfile`, voeg toe bij apt-get install of maak een nieuwe RUN statement. + +### Memory limits instellen + +In `docker-compose.yml`: +```yaml +deploy: + resources: + limits: + memory: 4G +``` + +## Claude Code CLI opties + +```bash +# Model kiezen +claude -m claude-opus-4 "vraag" +claude -m claude-sonnet-4 "vraag" + +# Context toevoegen +claude --context file1.java file2.java "refactor deze code" + +# Headless mode (non-interactive output) +claude -p "genereer code" + +# Working directory +claude --cwd /path/to/project "maak tests" +``` + +Zie volledige documentatie: https://code.claude.com/docs + +--- + +Veel plezier met coderen! πŸš€ diff --git a/check-setup.sh b/check-setup.sh new file mode 100644 index 0000000..f153157 --- /dev/null +++ b/check-setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +echo "πŸ” Claude Dev Container - Setup Check" +echo "======================================" +echo "" + +# Check if .env exists +if [ -f .env ]; then + echo "βœ… .env file exists" +else + echo "❌ .env file missing - copy from .env.example" + echo " Run: cp .env.example .env" +fi + +# Check Docker socket +if [ -e /var/run/docker.sock ]; then + echo "βœ… Docker socket found" + DOCKER_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || stat -f '%g' /var/run/docker.sock) + echo " Docker group ID: $DOCKER_GID" + echo "" + echo " ⚠️ Make sure docker-compose.yml has 'group_add: [\"$DOCKER_GID\"]'" +else + echo "⚠️ Docker socket not found at /var/run/docker.sock" + echo " This is normal if you're not on the Synology host" +fi + +# Check Docker +if command -v docker &> /dev/null; then + echo "βœ… Docker installed" + docker --version +else + echo "❌ Docker not found" +fi + +# Check Docker Compose +if docker compose version &> /dev/null; then + echo "βœ… Docker Compose available" + docker compose version +elif command -v docker-compose &> /dev/null; then + echo "βœ… Docker Compose available (standalone)" + docker-compose --version +else + echo "❌ Docker Compose not found" +fi + +echo "" +echo "======================================" +echo "Ready to build? Run: make build && make up" +echo "Or: docker compose build && docker compose up -d" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..66de218 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.8' + +services: + claude-dev: + build: . + container_name: claude-dev-container + restart: unless-stopped + + ports: + - "7681:7681" # ttyd (web terminal) + + environment: + # Set custom terminal credentials via .env file + - TERMINAL_USER=${TERMINAL_USER:-developer} + - TERMINAL_PASSWORD=${TERMINAL_PASSWORD:-changeme} + + volumes: + # Mount host Docker socket (for Synology) + - /var/run/docker.sock:/var/run/docker.sock + + # Persistent workspace + - /volume1/docker/claude-dev/workspace:/home/developer/workspace + + # Claude Code credentials (copy from Mac ~/.claude) + - /volume1/docker/claude-dev/claude-config:/home/developer/.claude + + # Run as developer user + user: "1000:1000" + + # Give access to docker group (typically GID 999 on Synology, adjust if needed) + group_add: + - "999" # Docker group - check with: getent group docker on your Synology diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..5855880 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Source SDKMAN for Java commands +source "$SDKMAN_DIR/bin/sdkman-init.sh" + +# Display startup info +echo "===================================" +echo "Claude Dev Container Starting..." +echo "===================================" +echo "Available Java versions:" +sdk list java | grep installed +echo "" +echo "Current Java version:" +java -version +echo "" +echo "Claude Code CLI: $(claude --version 2>/dev/null || echo 'installed')" +echo "" +echo "===================================" +echo "Services:" +echo " - Web terminal: http://localhost:7681" +echo "===================================" +echo "" +echo "Quick start:" +echo " claude chat # Start interactive chat" +echo " claude 'your prompt' # One-shot command" +echo " sdk list java # Show Java versions" +echo " sdk use java 17 # Switch Java version" +echo " docker ps # Docker commands work!" +echo "" +echo "===================================" + +# Get credentials from environment variables or use defaults +TERMINAL_USER=${TERMINAL_USER:-developer} +TERMINAL_PASSWORD=${TERMINAL_PASSWORD:-changeme} + +# Check if Claude credentials exist +if [ -f "$HOME/.claude/session.json" ]; then + echo "βœ… Claude Code credentials found - ready to use!" +else + echo "⚠️ No Claude credentials found" + echo " Copy ~/.claude from your Mac to ./claude-credentials/" +fi +echo "" + +# Start ttyd with basic auth +echo "Starting web terminal on port 7681..." +exec ttyd -p 7681 -c $TERMINAL_USER:$TERMINAL_PASSWORD bash diff --git a/setup-credentials.sh b/setup-credentials.sh new file mode 100644 index 0000000..2ee4597 --- /dev/null +++ b/setup-credentials.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +echo "πŸ” Claude Credentials Setup" +echo "============================" +echo "" + +# Check if running on Mac +if [[ "$OSTYPE" == "darwin"* ]]; then + echo "βœ… Running on Mac" + + # Check if ~/.claude exists + if [ -d "$HOME/.claude" ]; then + echo "βœ… Found Claude credentials at ~/.claude" + + # Create target directory + mkdir -p ./claude-credentials + + # Copy credentials + echo "" + echo "Copying credentials..." + cp -r "$HOME/.claude/"* ./claude-credentials/ 2>/dev/null + + if [ $? -eq 0 ]; then + echo "βœ… Credentials copied to ./claude-credentials/" + echo "" + echo "Next steps:" + echo "1. If deploying to Synology, upload this folder" + echo "2. Or build and run locally: make build && make up" + else + echo "❌ Failed to copy credentials" + exit 1 + fi + else + echo "❌ No Claude credentials found at ~/.claude" + echo "" + echo "Please login to Claude Code first:" + echo " 1. Install Claude Code CLI: npm install -g @anthropic-ai/claude-code" + echo " 2. Run: claude" + echo " 3. Complete the login flow" + echo " 4. Run this script again" + exit 1 + fi +else + echo "ℹ️ Not running on Mac" + echo "" + echo "To copy credentials from your Mac:" + echo "" + echo " scp -r ~/.claude/ user@this-machine:$(pwd)/claude-credentials" + echo "" + echo "Or manually copy the ~/.claude folder from your Mac" +fi + +echo "" +echo "============================"