diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..59e5e00 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,107 @@ +# syntax=docker/dockerfile:1.7 + +FROM ubuntu:24.04 + +ARG SANDBOX_UID=1001 +ARG SANDBOX_GID=1001 +ARG TARGETARCH + +ENV DEBIAN_FRONTEND=noninteractive +ENV NODE_VERSION=25.9.0 + +RUN --mount=type=cache,id=lab-ubuntu-apt-cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=lab-ubuntu-apt-lists,target=/var/lib/apt,sharing=locked \ + apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + bash \ + ca-certificates \ + curl \ + file \ + git \ + jq \ + libatomic1 \ + python3 \ + python3-pip \ + python3-venv \ + ripgrep \ + rsync \ + sudo \ + tini \ + unzip \ + wget \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* + +RUN set -eux; \ + case "${TARGETARCH:-amd64}" in \ + amd64) NODE_ARCH="x64" ;; \ + arm64) NODE_ARCH="arm64" ;; \ + *) echo "Unsupported TARGETARCH: ${TARGETARCH:-unset}" >&2; exit 1 ;; \ + esac; \ + curl -fsSLO "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz"; \ + tar -xJf "node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" -C /usr/local --strip-components=1; \ + rm -f "node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz"; \ + node --version; \ + npm --version + +RUN if ! getent group sandbox >/dev/null; then groupadd -g ${SANDBOX_GID} sandbox; fi \ + && if ! id -u sandbox >/dev/null 2>&1; then useradd -m -u ${SANDBOX_UID} -g ${SANDBOX_GID} -s /bin/bash sandbox; fi \ + && echo 'sandbox ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/sandbox \ + && chmod 0440 /etc/sudoers.d/sandbox + +RUN mkdir -p \ + /opt/sandbox-home-skel/.config \ + /opt/sandbox-home-skel/.local/bin \ + /opt/sandbox-home-skel/.local/lib/node_modules \ + /opt/sandbox-home-skel/.cache \ + /opt/sandbox-home-skel/.ssh \ + /opt/sandbox-home-skel/.npm \ + /opt/sandbox-home-skel/.cargo/bin \ + && printf '%s\n' \ + 'export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"' \ + 'export NPM_CONFIG_PREFIX="$HOME/.local"' \ + 'export npm_config_prefix="$HOME/.local"' \ + 'export EDITOR=vi' \ + >> /opt/sandbox-home-skel/.bashrc \ + && printf '%s\n' \ + 'prefix=/home/sandbox/.local' \ + 'cache=/home/sandbox/.npm' \ + > /opt/sandbox-home-skel/.npmrc \ + && printf '%s\n' \ + '[user]' \ + ' name = sandbox' \ + ' email = sandbox@example.invalid' \ + > /opt/sandbox-home-skel/.gitconfig \ + && touch /opt/sandbox-home-skel/.hushlogin \ + && chown -R sandbox:sandbox /opt/sandbox-home-skel + +ENV HOME=/home/sandbox +ENV NPM_CONFIG_PREFIX=/home/sandbox/.local +ENV npm_config_prefix=/home/sandbox/.local +ENV PATH=/home/sandbox/.local/bin:/home/sandbox/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +COPY --chmod=755 <<'EOF' /usr/local/bin/sandbox-entrypoint.sh +#!/usr/bin/env bash +set -euo pipefail + +HOME_DIR="${HOME:-/home/sandbox}" +SKEL_DIR="/opt/sandbox-home-skel" +SEED_MARKER="${HOME_DIR}/.sandbox-home-seeded" + +mkdir -p "${HOME_DIR}" "${HOME_DIR}/.local/bin" "${HOME_DIR}/.local/lib/node_modules" "${HOME_DIR}/.npm" + +if [ ! -e "${SEED_MARKER}" ]; then + rsync -a --no-o --no-g --ignore-existing "${SKEL_DIR}/" "${HOME_DIR}/" + touch "${SEED_MARKER}" +fi + +cd /workspace 2>/dev/null || cd "${HOME_DIR}" +exec "$@" +EOF + +USER sandbox +WORKDIR /workspace + +ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/sandbox-entrypoint.sh"] +CMD ["sleep", "infinity"] \ No newline at end of file