build daily
All checks were successful
Build Docker Image on Commit and Schedule / build-and-publish (push) Successful in 2m38s

This commit is contained in:
Merith 2025-07-27 08:58:10 -07:00
parent c2281e28e4
commit 53e074c7cf
5 changed files with 260 additions and 42 deletions

View file

@ -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:

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/home
/workspace

View file

@ -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"]

14
docker-compose.yml Normal file
View file

@ -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"

175
entrypoint.sh Normal file
View file

@ -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