From 53e074c7cfe8b4cec58322f7b5e7bd373727978f Mon Sep 17 00:00:00 2001 From: Merith Date: Sun, 27 Jul 2025 08:58:10 -0700 Subject: [PATCH] build daily --- .forgejo/workflows/build-on-commit.yml | 5 +- .gitignore | 2 + Dockerfile | 106 +++++++++------ docker-compose.yml | 14 ++ entrypoint.sh | 175 +++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 42 deletions(-) create mode 100644 .gitignore create mode 100644 docker-compose.yml create mode 100644 entrypoint.sh diff --git a/.forgejo/workflows/build-on-commit.yml b/.forgejo/workflows/build-on-commit.yml index fba6d8f..918df79 100644 --- a/.forgejo/workflows/build-on-commit.yml +++ b/.forgejo/workflows/build-on-commit.yml @@ -1,4 +1,4 @@ -name: Build Docker Image on Commit +name: Build Docker Image on Commit and Schedule on: push: @@ -6,6 +6,9 @@ on: - main tags: - '!' # Exclude tags + schedule: + # Run daily at 2:00 AM UTC to pick up base image updates + - cron: '0 2 * * *' jobs: build-and-publish: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..709fc42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/home +/workspace \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b673960..00399c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,51 +4,75 @@ USER root # Set environment variables ENV DEFAULT_WORKSPACE=/workspace -ENV DOCKER_USER=code +# Use the existing coder user from base image instead of non-existent 'code' user +ENV DOCKER_USER=coder # Define persistent volumes for /home and /workspace VOLUME ["/home", "/workspace"] -# Add Docker command support to image -RUN apt-get update && apt-get install ca-certificates curl \ - && install -m 0755 -d /etc/apt/keyrings \ - && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \ - && chmod a+r /etc/apt/keyrings/docker.asc -RUN echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ - $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null \ - && sudo apt-get update - -RUN apt-get install -y --no-install-recommends \ - docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - -# Install development tools with optimization for minimal package installs +# Layer 0: Base system update (foundation layer) RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - git \ - curl \ - wget \ - vim \ - zsh \ - tmux \ - htop \ - tree \ - jq \ - unzip \ - zip \ - gcc \ - g++ \ - make \ - cmake \ - python3 \ - python3-pip \ - python3-venv && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* + apt-get upgrade -y + +# Layer 1: Docker repository setup (changes rarely) +RUN apt-get install -y --no-install-recommends \ + ca-certificates \ + gnupg \ + lsb-release && \ + # Add Docker's official GPG key + install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \ + chmod a+r /etc/apt/keyrings/docker.asc && \ + # Add Docker repository + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + apt-get update + +# Layer 2: Docker installation (changes when Docker versions update) +RUN apt-get install -y --no-install-recommends \ + docker-ce \ + docker-ce-cli \ + containerd.io \ + docker-buildx-plugin \ + docker-compose-plugin && \ + # Add coder user to docker group for Docker-in-Docker + usermod -aG docker coder + +# Layer 3: Homebrew prerequisites (brew.sh requirements) +RUN apt-get install -y --no-install-recommends \ + sudo \ + build-essential \ + procps \ + curl \ + file \ + git + +# Layer 4: Code-server entrypoint (always fetch fresh during build) +RUN curl -fsSL -o /usr/bin/entrypoint-official.sh \ + https://raw.githubusercontent.com/coder/code-server/main/ci/release-image/entrypoint.sh && \ + chmod +x /usr/bin/entrypoint-official.sh + +# Copy our custom entrypoint that chainloads the official one +COPY entrypoint.sh /usr/bin/entrypoint.sh +RUN chmod +x /usr/bin/entrypoint.sh + +# Set required environment variables for code-server compatibility +ENV ENTRYPOINTD=/home/coder/entrypoint.d +ENV USER=coder +ENV HOME=/home/coder + +# Layer 5: Homebrew official requirements for Debian/Ubuntu +RUN apt-get install -y --no-install-recommends \ + sudo \ + build-essential \ + procps \ + curl \ + file \ + git + +# Final cleanup: Remove package lists and temporary files +RUN apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -## Workaround as above somehow removed the entrypoint.sh -RUN curl -o /usr/bin/entrypoint.sh https://raw.githubusercontent.com/coder/code-server/main/ci/release-image/entrypoint.sh && \ - chmod +x /usr/bin/entrypoint.sh - ENTRYPOINT ["/usr/bin/entrypoint.sh", "--bind-addr", "0.0.0.0:8080", "/workspace"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7e636d3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +services: + code-server: + #image: git.merith.xyz/oci/code-server:nightly + build: . + container_name: code-server + restart: no + ports: + - "8080:8080" + volumes: + - ./workspace:/workspace + - ./home:/home + environment: + PASSWORD: "TestPassword" + DEFAULT_WORKSPACE: "/workspace" \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..5d548b3 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,175 @@ +#!/bin/bash +set -e + +# Custom entrypoint for code-server with additional setup +# Supports both rooted Docker containers and rootless Podman containers +CURRENT_USER=$(whoami) +CURRENT_UID=$(id -u) +echo "🚀 Starting custom code-server entrypoint (running as $CURRENT_USER, UID: $CURRENT_UID)..." + +# Detect if we're running as root or not +IS_ROOT=false +if [ "$CURRENT_UID" -eq 0 ]; then + IS_ROOT=true + echo "🔐 Running in rooted container mode - will perform system setup" +else + echo "👤 Running in rootless container mode - assuming permissions already granted" +fi + +# Ensure proper home directory structure (critical for volume mounts) +echo "🏠 Setting up home directory structure..." + +# Create home directory for coder user if it doesn't exist +if [ ! -d "/home/coder" ]; then + echo "📁 Creating /home/coder directory..." + mkdir -p /home/coder +fi + +# Set ownership only if running as root +if [ "$IS_ROOT" = true ]; then + chown coder:coder /home/coder + chmod 755 /home/coder +else + # In rootless mode, just ensure it's accessible + chmod 755 /home/coder 2>/dev/null || true +fi + +# Set up essential dotfiles and shell configuration +if [ ! -f "/home/coder/.bashrc" ]; then + echo "⚙️ Creating default .bashrc..." + cat > /home/coder/.bashrc << 'EOF' +# ~/.bashrc: executed by bash(1) for non-login shells. + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +# Load Homebrew environment if available +if [ -d "/home/linuxbrew/.linuxbrew" ]; then + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" +fi + +# Some useful aliases +alias ll='ls -alF' +alias la='ls -A' +alias l='ls -CF' + +# Enable color support +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + alias grep='grep --color=auto' +fi +EOF + # Set ownership only if running as root + if [ "$IS_ROOT" = true ]; then + chown coder:coder /home/coder/.bashrc + fi +fi + +# Set up .profile for login shells +if [ ! -f "/home/coder/.profile" ]; then + echo "⚙️ Creating default .profile..." + cat > /home/coder/.profile << 'EOF' +# ~/.profile: executed by the command interpreter for login shells. + +# Load Homebrew environment if available +if [ -d "/home/linuxbrew/.linuxbrew" ]; then + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" +fi + +# Set PATH to include user's private bin if it exists +if [ -d "$HOME/bin" ] ; then + PATH="$HOME/bin:$PATH" +fi +EOF + # Set ownership only if running as root + if [ "$IS_ROOT" = true ]; then + chown coder:coder /home/coder/.profile + fi +fi + +# Install/Setup Homebrew if not already present +echo "🍺 Setting up Homebrew..." +if [ ! -d "/home/linuxbrew/.linuxbrew" ] || [ ! -f "/home/linuxbrew/.linuxbrew/bin/brew" ]; then + echo "📦 Installing Homebrew..." + + # Create linuxbrew user directory structure + mkdir -p /home/linuxbrew/.linuxbrew + + # Clone Homebrew repository + git clone --depth=1 https://github.com/Homebrew/brew /home/linuxbrew/.linuxbrew/Homebrew + + # Create bin directory and symlink + mkdir -p /home/linuxbrew/.linuxbrew/bin + ln -sf /home/linuxbrew/.linuxbrew/Homebrew/bin/brew /home/linuxbrew/.linuxbrew/bin/brew + + # Set proper ownership only if running as root + if [ "$IS_ROOT" = true ]; then + chown -R coder:coder /home/linuxbrew + fi + + echo "✅ Homebrew installed successfully!" +else + echo "✅ Homebrew already installed, ensuring proper ownership..." + # Ensure ownership is correct only if running as root (important for volume mounts) + if [ "$IS_ROOT" = true ]; then + chown -R coder:coder /home/linuxbrew + fi +fi + +# Create workspace directory if it doesn't exist +if [ ! -d "/workspace" ]; then + echo "📁 Creating workspace directory..." + mkdir -p /workspace +fi + +# Ensure proper ownership of workspace only if running as root +if [ "$IS_ROOT" = true ]; then + chown coder:coder /workspace + chmod 755 /workspace +else + # In rootless mode, just ensure it's accessible + chmod 755 /workspace 2>/dev/null || true +fi + +# Set up any workspace-specific initialization +if [ -f "/workspace/.devcontainer/init.sh" ]; then + echo "🛠️ Running workspace initialization script..." + chmod +x /workspace/.devcontainer/init.sh + if [ "$IS_ROOT" = true ]; then + # Run as coder user when root + su - coder -c "/workspace/.devcontainer/init.sh" + else + # Run directly when not root + /workspace/.devcontainer/init.sh + fi +fi + +# Ensure the coder user has access to docker if docker group exists (only when root) +if [ "$IS_ROOT" = true ] && getent group docker > /dev/null 2>&1; then + echo "🐳 Ensuring coder user is in docker group..." + usermod -aG docker coder +fi + +echo "✅ Setup complete, chainloading official entrypoint..." + +# Switch to coder user and chainload the official code-server entrypoint +if [ "$IS_ROOT" = true ]; then + echo "🔄 Switching to coder user and launching code-server..." + # Use su with proper environment setup when running as root + # Set required environment variables for code-server + export ENTRYPOINTD="/home/coder/entrypoint.d" + export USER="coder" + export HOME="/home/coder" + exec su - coder -c "export ENTRYPOINTD=\"/home/coder/entrypoint.d\" && export USER=\"coder\" && export HOME=\"/home/coder\" && cd /workspace && exec /usr/bin/entrypoint-official.sh $*" +else + echo "🔄 Launching code-server directly..." + # Run directly when not root (rootless mode) + export ENTRYPOINTD="${HOME}/entrypoint.d" + export USER="${USER:-$(whoami)}" + cd /workspace + exec /usr/bin/entrypoint-official.sh "$@" +fi