feat(@projects): ✨ add docker container wrapper for godot
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
5ef09a243c
commit
7678f4668f
2 changed files with 139 additions and 0 deletions
85
scripts/godot-docker.sh
Executable file
85
scripts/godot-docker.sh
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env bash
|
||||
# godot-docker.sh — run Godot Linux headless inside a freeze-proof Docker container.
|
||||
#
|
||||
# Why: `godot --headless --import` and similar commands kernel-panicked plum
|
||||
# twice and freeze apricot when run cold. Containers on macOS run inside a
|
||||
# Linux VM with its own kernel, fully isolated from macOS — no chance of
|
||||
# tripping the GPU/video kexts that caused the panics. Cgroup limits below
|
||||
# also keep the VM from starving itself.
|
||||
#
|
||||
# See: ~/.claude/plans/godot-container-runner.md
|
||||
#
|
||||
# Usage:
|
||||
# scripts/godot-docker.sh [args...] # passed straight to godot
|
||||
# scripts/godot-docker.sh --version # smoke test
|
||||
# scripts/godot-docker.sh --headless --import # warm the import cache
|
||||
# scripts/godot-docker.sh --headless --script res://addons/gut/gut_cmdln.gd -gexit -gtest=res://engine/tests/unit/test_city_buildable_helper.gd
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
DOCKERFILE="$REPO_ROOT/tools/docker/Dockerfile.godot"
|
||||
|
||||
IMAGE="mc-godot:4.6.2"
|
||||
VOLUME="mc-godot-cache"
|
||||
WORKDIR_IN_CONTAINER="/work/src/game"
|
||||
|
||||
# Cgroup hard caps so the container can't starve the host VM.
|
||||
# Defaults sized for Docker Desktop with ≥7 GiB allocated.
|
||||
CPUS="${MC_GODOT_CPUS:-4}"
|
||||
MEMORY="${MC_GODOT_MEMORY:-6g}"
|
||||
PIDS_LIMIT="${MC_GODOT_PIDS:-256}"
|
||||
|
||||
ensure_image() {
|
||||
if docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
echo "[godot-docker] image $IMAGE not found — building..." >&2
|
||||
docker build \
|
||||
--tag "$IMAGE" \
|
||||
--file "$DOCKERFILE" \
|
||||
"$REPO_ROOT/tools/docker"
|
||||
}
|
||||
|
||||
ensure_volume() {
|
||||
if docker volume inspect "$VOLUME" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
echo "[godot-docker] creating named volume $VOLUME for warm import cache" >&2
|
||||
docker volume create "$VOLUME" >/dev/null
|
||||
}
|
||||
|
||||
ensure_docker_running() {
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "ERROR: Docker daemon not reachable. Start Docker Desktop first." >&2
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
ensure_docker_running
|
||||
ensure_image
|
||||
ensure_volume
|
||||
|
||||
# Force a TTY only when stdout is a terminal; CI invocations stay non-interactive.
|
||||
local tty_flag=""
|
||||
if [[ -t 1 ]]; then
|
||||
tty_flag="-t"
|
||||
fi
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
-i $tty_flag \
|
||||
--cpus "$CPUS" \
|
||||
--memory "$MEMORY" \
|
||||
--memory-swap "$MEMORY" \
|
||||
--pids-limit "$PIDS_LIMIT" \
|
||||
--volume "$REPO_ROOT:/work" \
|
||||
--volume "$VOLUME:/work/src/game/.godot" \
|
||||
--workdir "$WORKDIR_IN_CONTAINER" \
|
||||
"$IMAGE" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
54
tools/docker/Dockerfile.godot
Normal file
54
tools/docker/Dockerfile.godot
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Godot 4.6.2 Linux headless — freeze-proof runtime for asset import + GUT tests.
|
||||
# See ~/.claude/plans/godot-container-runner.md for why this exists.
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
ARG GODOT_VERSION=4.6.2
|
||||
ARG GODOT_RELEASE=stable
|
||||
# Pinned official SHA256 — update together with GODOT_VERSION.
|
||||
# Compute via: sha256sum Godot_v${GODOT_VERSION}-${GODOT_RELEASE}_linux.x86_64.zip
|
||||
ARG GODOT_SHA256=
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
wget \
|
||||
unzip \
|
||||
libgl1-mesa-glx \
|
||||
libfontconfig1 \
|
||||
libxi6 \
|
||||
libxrandr2 \
|
||||
libxcursor1 \
|
||||
libxinerama1 \
|
||||
libasound2 \
|
||||
libpulse0 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Detect arch at build time so this image works on both Apple-silicon Docker
|
||||
# Desktop (linux/arm64) and amd64 hosts.
|
||||
RUN set -eux; \
|
||||
arch="$(dpkg --print-architecture)"; \
|
||||
case "$arch" in \
|
||||
arm64) godot_arch="linux.arm64" ;; \
|
||||
amd64) godot_arch="linux.x86_64" ;; \
|
||||
*) echo "unsupported arch: $arch" >&2; exit 1 ;; \
|
||||
esac; \
|
||||
url="https://github.com/godotengine/godot-builds/releases/download/${GODOT_VERSION}-${GODOT_RELEASE}/Godot_v${GODOT_VERSION}-${GODOT_RELEASE}_${godot_arch}.zip"; \
|
||||
wget -q -O /tmp/godot.zip "$url"; \
|
||||
unzip -q /tmp/godot.zip -d /opt; \
|
||||
mv /opt/Godot_v${GODOT_VERSION}-${GODOT_RELEASE}_${godot_arch} /usr/local/bin/godot; \
|
||||
chmod +x /usr/local/bin/godot; \
|
||||
rm /tmp/godot.zip
|
||||
|
||||
# Runtime user with a stable uid/gid so bind-mounted files don't get chown'd
|
||||
# by container writes. Docker Desktop on macOS handles uid mapping
|
||||
# transparently, so picking 1000 is fine.
|
||||
RUN useradd --create-home --uid 1000 --shell /bin/bash godot
|
||||
|
||||
USER godot
|
||||
WORKDIR /work
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/godot"]
|
||||
CMD ["--version"]
|
||||
Loading…
Add table
Reference in a new issue