diff --git a/.dockerignore b/.dockerignore index 9bcce7a80..c08bc0c03 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,7 @@ +# Ignore everything by default ** -!release-packages -!ci + +# Include only what's needed for the Railway build +!Dockerfile +!railway-entrypoint.sh +!railway.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..380af387f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# Custom code-server image for Railway with persistent Node.js and extensions +FROM codercom/code-server:latest + +USER root + +# Install Node.js 20 LTS +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y nodejs \ + && npm install -g npm@latest \ + && 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 +ENV HOME=/home/coder +ENV USER=coder + +# Set XDG directories to use the persistent volume +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}" + +# Set entrypoint.d to the persistent volume for custom startup scripts +ENV ENTRYPOINTD=/home/coder/entrypoint.d + +# Create necessary directories +RUN mkdir -p /home/coder/.local/share \ + /home/coder/.config \ + /home/coder/.cache \ + /home/coder/.local/state \ + /home/coder/.local/bin \ + /home/coder/entrypoint.d \ + && 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 + +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", "."] diff --git a/railway-entrypoint.sh b/railway-entrypoint.sh new file mode 100644 index 000000000..c63536dbb --- /dev/null +++ b/railway-entrypoint.sh @@ -0,0 +1,68 @@ +#!/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 + +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" + +# Ensure HOME is set correctly (Railway might override it) +export HOME=/home/coder + +# 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" + +# Ensure the code-server data directory exists +mkdir -p "$XDG_DATA_HOME/code-server" + +# 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 + + # 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 + + # 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 + + # 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 + + echo "Created symlinks from /root to $HOME for persistence" +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" + +# 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" + fi + done +fi + +echo "=== Starting code-server ===" + +# Start code-server with dumb-init for proper signal handling +exec dumb-init /usr/bin/code-server "$@" diff --git a/railway.json b/railway.json new file mode 100644 index 000000000..1188f2743 --- /dev/null +++ b/railway.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://railway.app/railway.schema.json", + "build": { + "builder": "DOCKERFILE", + "dockerfilePath": "Dockerfile" + }, + "deploy": { + "startCommand": null, + "restartPolicyType": "ON_FAILURE", + "restartPolicyMaxRetries": 10 + } +}