mirror of
https://github.com/coder/code-server.git
synced 2026-02-19 18:01:15 +08:00
Easy install Claude Code
This commit is contained in:
parent
d868d96535
commit
da6737c5ba
77
Dockerfile
77
Dockerfile
@ -1,46 +1,97 @@
|
||||
# Custom code-server image for Railway with persistent Node.js and extensions
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Claude Code & Node.js Ready
|
||||
# Browser-based VSCode with persistent extensions and Node.js
|
||||
# https://github.com/sphinxcode/code-server
|
||||
# ============================================================================
|
||||
|
||||
FROM codercom/code-server:latest
|
||||
|
||||
USER root
|
||||
|
||||
# Install Node.js 20 LTS
|
||||
# Install FALLBACK Node.js and essential development tools
|
||||
# Volume-installed versions take priority at runtime via PATH ordering
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
nodejs \
|
||||
git \
|
||||
curl \
|
||||
wget \
|
||||
unzip \
|
||||
jq \
|
||||
htop \
|
||||
vim \
|
||||
nano \
|
||||
ripgrep \
|
||||
&& npm install -g npm@latest \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set HOME to /home/coder (the volume mount point on Railway)
|
||||
# This ensures all user data goes to the persistent volume
|
||||
# ============================================================================
|
||||
# PERSISTENCE CONFIGURATION
|
||||
# Default paths - can be overridden via CODER_HOME environment variable
|
||||
# ============================================================================
|
||||
|
||||
ENV HOME=/home/coder
|
||||
ENV USER=coder
|
||||
|
||||
# Set XDG directories to use the persistent volume
|
||||
# XDG Base Directory Specification
|
||||
ENV XDG_DATA_HOME=/home/coder/.local/share
|
||||
ENV XDG_CONFIG_HOME=/home/coder/.config
|
||||
ENV XDG_CACHE_HOME=/home/coder/.cache
|
||||
ENV XDG_STATE_HOME=/home/coder/.local/state
|
||||
|
||||
# Ensure Node.js is in PATH and add code-server CLI
|
||||
ENV PATH="/usr/bin:/usr/local/bin:/home/coder/.local/bin:/home/coder/.local/node/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}"
|
||||
# ============================================================================
|
||||
# PATH PRIORITY ORDER (volume paths FIRST, image paths LAST)
|
||||
# This ensures user-installed tools on the volume take precedence
|
||||
# ============================================================================
|
||||
|
||||
# Set entrypoint.d to the persistent volume for custom startup scripts
|
||||
ENV PATH="/home/coder/.local/node/bin:/home/coder/.claude/local:/home/coder/.local/bin:/home/coder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}"
|
||||
|
||||
# Custom startup scripts directory (on volume)
|
||||
ENV ENTRYPOINTD=/home/coder/entrypoint.d
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p /home/coder/.local/share \
|
||||
# ============================================================================
|
||||
# DIRECTORY SETUP
|
||||
# ============================================================================
|
||||
|
||||
RUN mkdir -p \
|
||||
/home/coder/.local/share \
|
||||
/home/coder/.config \
|
||||
/home/coder/.cache \
|
||||
/home/coder/.local/state \
|
||||
/home/coder/.local/bin \
|
||||
/home/coder/.local/node \
|
||||
/home/coder/.claude \
|
||||
/home/coder/entrypoint.d \
|
||||
/home/coder/workspace \
|
||||
&& chown -R 1000:1000 /home/coder
|
||||
|
||||
# Copy custom entrypoint
|
||||
COPY railway-entrypoint.sh /usr/bin/railway-entrypoint.sh
|
||||
RUN chmod +x /usr/bin/railway-entrypoint.sh
|
||||
|
||||
# ============================================================================
|
||||
# FALLBACK CLAUDE CODE CLI INSTALLATION
|
||||
# Installed to /usr/local/bin as fallback - volume version takes priority
|
||||
# ============================================================================
|
||||
|
||||
RUN curl -fsSL https://claude.ai/install.sh | bash \
|
||||
&& if [ -f /root/.claude/local/claude ]; then \
|
||||
mv /root/.claude/local/claude /usr/local/bin/claude; \
|
||||
chmod +x /usr/local/bin/claude; \
|
||||
fi \
|
||||
&& rm -rf /root/.claude
|
||||
|
||||
# ============================================================================
|
||||
# RUNTIME
|
||||
# Note: We run as root for compatibility with existing volumes
|
||||
# The entrypoint creates symlinks to ensure persistence
|
||||
# ============================================================================
|
||||
|
||||
WORKDIR /home/coder/workspace
|
||||
EXPOSE 8080
|
||||
|
||||
# Use our custom entrypoint that handles Railway's root user
|
||||
ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"]
|
||||
CMD ["--bind-addr", "0.0.0.0:8080", "."]
|
||||
CMD ["--bind-addr", "0.0.0.0:8080", "/home/coder/workspace"]
|
||||
|
||||
|
||||
94
README.md
Normal file
94
README.md
Normal file
@ -0,0 +1,94 @@
|
||||
# VSCode Cloud IDE
|
||||
|
||||
**Browser-based VSCode with Claude Code & Node.js**
|
||||
|
||||
[](https://railway.com/template/TEMPLATE_ID)
|
||||
|
||||
Cloud IDE with persistent extensions, settings, and tools. Zero configuration.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Claude Code** & **Node.js 20** pre-installed
|
||||
- Extensions persist across redeployments
|
||||
- Volume-installed tools take priority (update when YOU want)
|
||||
- Custom startup scripts supported
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Claude Code ready to use
|
||||
claude
|
||||
|
||||
# Node.js ready to use
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How Updates Work
|
||||
|
||||
| Component | Behavior |
|
||||
|-----------|----------|
|
||||
| **Volume tools** | YOU control updates. Install to `~/.local/node/` or `~/.claude/local/` |
|
||||
| **Image tools** | Auto-update on redeploy (fallback if no volume version) |
|
||||
| **Extensions** | Never reset (persisted on volume) |
|
||||
|
||||
The startup logs show `[volume]` or `[image]` next to each tool.
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `PASSWORD` | Yes | - | Login password |
|
||||
| `CODER_HOME` | No | `/home/coder` | Volume mount path |
|
||||
|
||||
---
|
||||
|
||||
## Custom Volume Path
|
||||
|
||||
If you change the volume mount location:
|
||||
|
||||
```
|
||||
CODER_HOME=/your/volume/path
|
||||
```
|
||||
|
||||
Everything adapts automatically.
|
||||
|
||||
---
|
||||
|
||||
## Custom Startup Scripts
|
||||
|
||||
Add to `$CODER_HOME/entrypoint.d/`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
git config --global user.name "Your Name"
|
||||
```
|
||||
|
||||
Make executable: `chmod +x script.sh`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Check |
|
||||
|-------|-------|
|
||||
| Wrong Node version | Look for `[volume]` vs `[image]` in logs |
|
||||
| Extensions missing | Verify volume at `CODER_HOME` |
|
||||
| Claude not found | Run `which claude` to verify PATH |
|
||||
|
||||
---
|
||||
|
||||
## Credits
|
||||
|
||||
- [code-server](https://github.com/coder/code-server) by Coder
|
||||
- [Claude Code](https://github.com/anthropics/claude-code) by Anthropic
|
||||
|
||||
**License:** MIT
|
||||
@ -1,68 +1,185 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Railway runs containers as root, but we want all data in /home/coder (the volume)
|
||||
# This script ensures proper environment setup for persistence
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Entrypoint
|
||||
# Robust entrypoint with volume-first tool priority
|
||||
# ============================================================================
|
||||
|
||||
echo "=== Railway Code-Server Startup ==="
|
||||
echo "User: $(whoami) (UID: $(id -u))"
|
||||
echo "HOME: $HOME"
|
||||
echo "XDG_DATA_HOME: $XDG_DATA_HOME"
|
||||
echo "XDG_CONFIG_HOME: $XDG_CONFIG_HOME"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Ensure HOME is set correctly (Railway might override it)
|
||||
export HOME=/home/coder
|
||||
# ============================================================================
|
||||
# CONFIGURABLE PATHS
|
||||
# Users can override CODER_HOME to change the volume mount point
|
||||
# ============================================================================
|
||||
|
||||
# Ensure XDG directories exist and are writable
|
||||
mkdir -p "$XDG_DATA_HOME" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_STATE_HOME"
|
||||
mkdir -p "$HOME/.local/bin" "$HOME/entrypoint.d"
|
||||
CODER_HOME="${CODER_HOME:-/home/coder}"
|
||||
|
||||
# Ensure the code-server data directory exists
|
||||
mkdir -p "$XDG_DATA_HOME/code-server"
|
||||
export HOME="$CODER_HOME"
|
||||
export XDG_DATA_HOME="$CODER_HOME/.local/share"
|
||||
export XDG_CONFIG_HOME="$CODER_HOME/.config"
|
||||
export XDG_CACHE_HOME="$CODER_HOME/.cache"
|
||||
export XDG_STATE_HOME="$CODER_HOME/.local/state"
|
||||
|
||||
# PATH: Volume paths FIRST (user installs), image paths LAST (fallbacks)
|
||||
export PATH="$CODER_HOME/.local/node/bin:$CODER_HOME/.claude/local:$CODER_HOME/.local/bin:$CODER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH"
|
||||
|
||||
echo "→ User: $(whoami) (UID: $(id -u))"
|
||||
echo "→ HOME: $HOME"
|
||||
|
||||
# ============================================================================
|
||||
# DIRECTORY CREATION
|
||||
# ============================================================================
|
||||
|
||||
create_dirs() {
|
||||
mkdir -p "$XDG_DATA_HOME" \
|
||||
"$XDG_CONFIG_HOME" \
|
||||
"$XDG_CACHE_HOME" \
|
||||
"$XDG_STATE_HOME" \
|
||||
"$HOME/.local/bin" \
|
||||
"$HOME/.local/node" \
|
||||
"$HOME/.claude" \
|
||||
"$HOME/entrypoint.d" \
|
||||
"$HOME/workspace" \
|
||||
"$XDG_DATA_HOME/code-server/extensions" \
|
||||
"$XDG_CONFIG_HOME/code-server" 2>/dev/null || true
|
||||
}
|
||||
create_dirs
|
||||
|
||||
# ============================================================================
|
||||
# ROOT USER SYMLINKS
|
||||
# When running as root, symlink /root directories to the volume
|
||||
# ============================================================================
|
||||
|
||||
# Set up VS Code Server data directory symlink if running as root
|
||||
# This ensures extensions installed by code-server persist
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
# Create root's directories pointing to volume
|
||||
mkdir -p /root/.local
|
||||
echo "→ Running as root - creating persistence symlinks..."
|
||||
|
||||
# Symlink root's local share to the volume (for VS Code extensions)
|
||||
if [ ! -L /root/.local/share ]; then
|
||||
rm -rf /root/.local/share 2>/dev/null || true
|
||||
ln -sf "$XDG_DATA_HOME" /root/.local/share
|
||||
fi
|
||||
mkdir -p /root/.local 2>/dev/null || true
|
||||
|
||||
# Symlink root's config to the volume
|
||||
if [ ! -L /root/.config ]; then
|
||||
rm -rf /root/.config 2>/dev/null || true
|
||||
ln -sf "$XDG_CONFIG_HOME" /root/.config
|
||||
fi
|
||||
for dir in ".local/share" ".local/node" ".config" ".cache" ".claude"; do
|
||||
target="$CODER_HOME/$dir"
|
||||
link="/root/$dir"
|
||||
|
||||
# Symlink root's cache to the volume
|
||||
if [ ! -L /root/.cache ]; then
|
||||
rm -rf /root/.cache 2>/dev/null || true
|
||||
ln -sf "$XDG_CACHE_HOME" /root/.cache
|
||||
fi
|
||||
if [ -d "$target" ] && [ ! -L "$link" ]; then
|
||||
rm -rf "$link" 2>/dev/null || true
|
||||
mkdir -p "$(dirname "$link")" 2>/dev/null || true
|
||||
ln -sf "$target" "$link" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Created symlinks from /root to $HOME for persistence"
|
||||
echo " ✓ Root directories symlinked to $CODER_HOME"
|
||||
fi
|
||||
|
||||
# Ensure Node.js is accessible
|
||||
echo "Node.js version: $(node --version 2>/dev/null || echo 'Not found in PATH')"
|
||||
echo "npm version: $(npm --version 2>/dev/null || echo 'Not found in PATH')"
|
||||
echo "PATH: $PATH"
|
||||
# ============================================================================
|
||||
# FIRST RUN SETUP
|
||||
# ============================================================================
|
||||
|
||||
FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized"
|
||||
|
||||
if [ ! -f "$FIRST_RUN_MARKER" ]; then
|
||||
echo "→ First run detected - initializing..."
|
||||
|
||||
mkdir -p "$XDG_CONFIG_HOME/code-server" 2>/dev/null || true
|
||||
|
||||
if [ ! -f "$HOME/workspace/README.md" ]; then
|
||||
cat > "$HOME/workspace/README.md" << 'WELCOME' 2>/dev/null || true
|
||||
# Welcome to VSCode Cloud IDE
|
||||
|
||||
Your cloud development environment is ready!
|
||||
|
||||
## Features
|
||||
|
||||
- **Claude Code CLI** - Pre-installed and ready to use
|
||||
- **Node.js 20 LTS** - Pre-installed and ready to use
|
||||
- **Persistent Extensions** - Install once, keep forever
|
||||
- **Full Terminal** - npm, git, and more
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Open the Extensions panel (Ctrl+Shift+X)
|
||||
2. Install your favorite extensions (they persist!)
|
||||
3. Start coding in this workspace
|
||||
|
||||
## Using Claude Code
|
||||
|
||||
```bash
|
||||
claude
|
||||
```
|
||||
|
||||
You'll need to authenticate with your Anthropic API key on first use.
|
||||
|
||||
Happy coding! 🚀
|
||||
WELCOME
|
||||
fi
|
||||
|
||||
touch "$FIRST_RUN_MARKER" 2>/dev/null || true
|
||||
echo " ✓ Initialization complete"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# ENVIRONMENT VERIFICATION
|
||||
# Shows which version is being used (volume vs image)
|
||||
# ============================================================================
|
||||
|
||||
echo ""
|
||||
echo "Environment:"
|
||||
|
||||
# Node.js - show source
|
||||
if [ -x "$CODER_HOME/.local/node/bin/node" ]; then
|
||||
echo " → Node.js: $(node --version 2>/dev/null) [volume]"
|
||||
else
|
||||
echo " → Node.js: $(node --version 2>/dev/null || echo 'not found') [image]"
|
||||
fi
|
||||
|
||||
# npm
|
||||
echo " → npm: $(npm --version 2>/dev/null || echo 'not found')"
|
||||
|
||||
# git
|
||||
echo " → git: $(git --version 2>/dev/null | cut -d' ' -f3 || echo 'not found')"
|
||||
|
||||
# Claude Code - show source
|
||||
if [ -x "$CODER_HOME/.claude/local/claude" ]; then
|
||||
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume]"
|
||||
elif command -v claude &>/dev/null; then
|
||||
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [image]"
|
||||
else
|
||||
echo " → claude: not installed"
|
||||
fi
|
||||
|
||||
# Extensions count
|
||||
if [ -d "$XDG_DATA_HOME/code-server/extensions" ]; then
|
||||
EXT_COUNT=$(find "$XDG_DATA_HOME/code-server/extensions" -maxdepth 1 -type d 2>/dev/null | wc -l)
|
||||
EXT_COUNT=$((EXT_COUNT - 1))
|
||||
if [ $EXT_COUNT -gt 0 ]; then
|
||||
echo " → Extensions: $EXT_COUNT installed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# CUSTOM STARTUP SCRIPTS
|
||||
# ============================================================================
|
||||
|
||||
# Run any custom startup scripts from entrypoint.d
|
||||
if [ -d "$HOME/entrypoint.d" ]; then
|
||||
for script in "$HOME/entrypoint.d"/*.sh; do
|
||||
if [ -f "$script" ] && [ -x "$script" ]; then
|
||||
echo "Running startup script: $script"
|
||||
"$script"
|
||||
echo ""
|
||||
echo "Running: $(basename "$script")"
|
||||
"$script" || echo " ⚠ Script exited with code $?"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "=== Starting code-server ==="
|
||||
# ============================================================================
|
||||
# START CODE-SERVER
|
||||
# ============================================================================
|
||||
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════════════════════════════════"
|
||||
echo "Starting code-server..."
|
||||
echo "════════════════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
# Start code-server with dumb-init for proper signal handling
|
||||
exec dumb-init /usr/bin/code-server "$@"
|
||||
|
||||
13
railway.toml
Normal file
13
railway.toml
Normal file
@ -0,0 +1,13 @@
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Configuration
|
||||
# ============================================================================
|
||||
|
||||
[build]
|
||||
builder = "DOCKERFILE"
|
||||
dockerfilePath = "Dockerfile"
|
||||
|
||||
[deploy]
|
||||
healthcheckPath = "/healthz"
|
||||
healthcheckTimeout = 300
|
||||
restartPolicyType = "ON_FAILURE"
|
||||
restartPolicyMaxRetries = 10
|
||||
Loading…
x
Reference in New Issue
Block a user