Chessistics/.devcontainer/Dockerfile

164 lines
5 KiB
Text
Raw Normal View History

2026-04-10 17:14:09 +02:00
FROM node:20
ARG TZ
ENV TZ="$TZ"
ARG CLAUDE_CODE_VERSION=latest
# Install basic development tools and iptables/ipset
RUN apt-get update && apt-get install -y --no-install-recommends \
less \
git \
procps \
sudo \
fzf \
zsh \
man-db \
unzip \
gnupg2 \
gh \
iptables \
ipset \
iproute2 \
dnsutils \
aggregate \
jq \
nano \
vim \
Headless Linux dev container: Godot + .NET + Xvfb for autonomous testing Claude Code running inside the project's dev container can now build the game, launch a real Godot instance under Xvfb, and drive the automation harness end-to-end — no Windows dependency. Dockerfile adds (as root, before USER node): - X11 / Mesa software GL / audio runtime deps + python3 - .NET SDK 9.0 via upstream dot.net install script -> /usr/local/dotnet - Godot 4.6.2-stable mono Linux x86_64 -> /opt/godot/godot - /usr/local/bin/godot-xvfb wrapper: auto-wraps invocations in xvfb-run -a --server-args="-screen 0 1280x720x24 ..." harness.py picks GODOT_BIN from env, defaults to /opt/godot/godot on Linux, and auto-wraps the subprocess in xvfb-run when DISPLAY is unset. Windows code path unchanged. init-firewall.sh adds api.nuget.org to the allowlist so dotnet restore works post-boot. Godot + .NET SDK are fetched at image build time, before the firewall exists. New docs: - autonomous_plan.md: design rationale, alternatives considered - README.md: launch instructions for Windows terminal / Docker Desktop / VS Code Dev Containers / WSL2 natif - CLAUDE.md already documents the harness (done in previous commit) Validation: docker build succeeds; inside the container, dotnet --version =9.0.313, godot --version=4.6.2.stable.mono, dotnet test=102/102, python3 tools/automation/smoke.py passes end-to-end with 14 non-black 1280x720 PNGs. Mission 1 screenshot is visually identical to the Windows build, and Xvfb determinism is a bonus (det_a.png ≡ det_b.png bytewise).
2026-04-17 16:57:56 +02:00
ca-certificates \
curl \
wget \
2026-04-10 17:14:09 +02:00
&& apt-get clean && rm -rf /var/lib/apt/lists/*
Headless Linux dev container: Godot + .NET + Xvfb for autonomous testing Claude Code running inside the project's dev container can now build the game, launch a real Godot instance under Xvfb, and drive the automation harness end-to-end — no Windows dependency. Dockerfile adds (as root, before USER node): - X11 / Mesa software GL / audio runtime deps + python3 - .NET SDK 9.0 via upstream dot.net install script -> /usr/local/dotnet - Godot 4.6.2-stable mono Linux x86_64 -> /opt/godot/godot - /usr/local/bin/godot-xvfb wrapper: auto-wraps invocations in xvfb-run -a --server-args="-screen 0 1280x720x24 ..." harness.py picks GODOT_BIN from env, defaults to /opt/godot/godot on Linux, and auto-wraps the subprocess in xvfb-run when DISPLAY is unset. Windows code path unchanged. init-firewall.sh adds api.nuget.org to the allowlist so dotnet restore works post-boot. Godot + .NET SDK are fetched at image build time, before the firewall exists. New docs: - autonomous_plan.md: design rationale, alternatives considered - README.md: launch instructions for Windows terminal / Docker Desktop / VS Code Dev Containers / WSL2 natif - CLAUDE.md already documents the harness (done in previous commit) Validation: docker build succeeds; inside the container, dotnet --version =9.0.313, godot --version=4.6.2.stable.mono, dotnet test=102/102, python3 tools/automation/smoke.py passes end-to-end with 14 non-black 1280x720 PNGs. Mission 1 screenshot is visually identical to the Windows build, and Xvfb determinism is a bonus (det_a.png ≡ det_b.png bytewise).
2026-04-17 16:57:56 +02:00
# -----------------------------------------------------------------------------
# Chessistics: headless Godot + .NET SDK
# -----------------------------------------------------------------------------
# 1. Xvfb + Mesa software GL + X/audio runtime deps for Godot's GL-compatibility renderer
RUN apt-get update && apt-get install -y --no-install-recommends \
xvfb \
xauth \
x11-utils \
libx11-6 \
libxcursor1 \
libxinerama1 \
libxrandr2 \
libxi6 \
libxext6 \
libxrender1 \
libxfixes3 \
libxss1 \
libxkbcommon0 \
libxkbcommon-x11-0 \
libgl1 \
libglx-mesa0 \
libgl1-mesa-dri \
libglu1-mesa \
libegl1 \
libgles2 \
libasound2 \
libpulse0 \
libfontconfig1 \
libfreetype6 \
libdbus-1-3 \
libudev1 \
fonts-dejavu-core \
python3 \
python3-pip \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# 2. .NET SDK 9.0 via the upstream install script (arch-agnostic, no apt repo needed)
RUN curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh \
&& bash /tmp/dotnet-install.sh --channel 9.0 --install-dir /usr/local/dotnet \
&& ln -s /usr/local/dotnet/dotnet /usr/local/bin/dotnet \
&& rm /tmp/dotnet-install.sh
ENV DOTNET_ROOT=/usr/local/dotnet
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
ENV DOTNET_NOLOGO=1
# 3. Godot 4.6.2-stable Mono for Linux x86_64
# The zip contains a directory like "Godot_v..._mono_linux_x86_64/" with
# an executable whose exact filename has varied across releases
# ("Godot_v..._mono_linux.x86_64" on 4.x). Locate it dynamically.
ARG GODOT_VERSION=4.6.2-stable
RUN mkdir -p /opt/godot \
&& cd /tmp \
&& wget -q "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_mono_linux_x86_64.zip" \
&& unzip -q "Godot_v${GODOT_VERSION}_mono_linux_x86_64.zip" -d /opt/godot \
&& GODOT_EXE="$(find /opt/godot -maxdepth 3 -type f \( -name 'Godot_v*mono_linux*x86_64' -o -name 'Godot_v*mono_linux*x86_64' \) | head -1)" \
&& if [ -z "$GODOT_EXE" ]; then echo "Godot executable not found in zip" && ls -R /opt/godot && exit 1; fi \
&& chmod +x "$GODOT_EXE" \
&& ln -sf "$GODOT_EXE" /opt/godot/godot \
&& rm "Godot_v${GODOT_VERSION}_mono_linux_x86_64.zip"
ENV GODOT_BIN=/opt/godot/godot
ENV PATH=$PATH:/opt/godot:/usr/local/dotnet
# 4. xvfb wrapper — any Godot invocation gets its own virtual 1280x720x24 display.
# Usage: `godot-xvfb --path /workspace ...` or let tools/automation/harness.py
# invoke it automatically on Linux.
COPY godot-xvfb.sh /usr/local/bin/godot-xvfb
RUN chmod +x /usr/local/bin/godot-xvfb
2026-04-10 17:14:09 +02:00
# Ensure default node user has access to /usr/local/share
RUN mkdir -p /usr/local/share/npm-global && \
chown -R node:node /usr/local/share
ARG USERNAME=node
# Persist bash history.
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
&& mkdir /commandhistory \
&& touch /commandhistory/.bash_history \
&& chown -R $USERNAME /commandhistory
# Set `DEVCONTAINER` environment variable to help with orientation
ENV DEVCONTAINER=true
# Create workspace and config directories and set permissions
RUN mkdir -p /workspace /home/node/.claude && \
chown -R node:node /workspace /home/node/.claude
WORKDIR /workspace
ARG GIT_DELTA_VERSION=0.18.2
RUN ARCH=$(dpkg --print-architecture) && \
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
# Set up non-root user
USER node
# Install global packages
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin
# Set the default shell to zsh rather than sh
ENV SHELL=/bin/zsh
# Set the default editor and visual
ENV EDITOR=nano
ENV VISUAL=nano
# Default powerline10k theme
ARG ZSH_IN_DOCKER_VERSION=1.2.0
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \
-p git \
-p fzf \
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
-a "source /usr/share/doc/fzf/examples/completion.zsh" \
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
-x
# Install Claude
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
# Copy and set up firewall script
COPY init-firewall.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/init-firewall.sh && \
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
chmod 0440 /etc/sudoers.d/node-firewall
USER node