mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
flake.nix (authoritative — Nix-built OCI image): - pythonEnv: add mpmath, matplotlib, seaborn, pandas, polars, scikit-learn - New rEnv binding: R via rWrapper with tidyverse, ggplot2, dplyr, tidyr, readr, purrr, stringr, forcats, lubridate, MASS, Matrix, survival, knitr, rmarkdown - devPkgs: add texliveFull, gnuplot, maxima, wxmaxima, octave, rEnv, typst - PATH env: expose texliveFull, typst, gnuplot, maxima, octave, rEnv bins Dockerfile (Alpine reference — kept in sync): - apk: add texlive-full, gnuplot, maxima, octave, R - New RUN layer: typst static binary from GitHub releases (musl build) - uv pip install: add mpmath, matplotlib, seaborn, pandas, polars, scikit-learn Note: sage is not packaged in nixpkgs 24.11; mpmath covers arbitrary-precision arithmetic needs. wxmaxima omitted from Dockerfile (requires display server; headless image). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
172 lines
6.7 KiB
Docker
172 lines
6.7 KiB
Docker
FROM alpine:3.19
|
|
|
|
# ── System packages ───────────────────────────────────────────────────────────
|
|
# Core build + dev tools
|
|
RUN apk add --no-cache \
|
|
bash \
|
|
build-base \
|
|
git \
|
|
curl \
|
|
wget \
|
|
openssh-client \
|
|
rsync \
|
|
zstd \
|
|
jq \
|
|
ripgrep \
|
|
# Graphviz for visualisation helpers
|
|
graphviz \
|
|
# Node / npm for JS tooling
|
|
nodejs \
|
|
npm \
|
|
# Python runtime + package managers
|
|
python3 \
|
|
py3-pip \
|
|
pipx \
|
|
# PostgreSQL client libs (needed by psycopg2 --no-binary build)
|
|
postgresql16-client \
|
|
postgresql16-dev \
|
|
libpq-dev \
|
|
# SSL / crypto headers (boto3, requests, psycopg2)
|
|
openssl-dev \
|
|
# CFFI / ffi headers
|
|
libffi-dev \
|
|
# Needed for some science packages (scipy, etc.)
|
|
gfortran \
|
|
openblas-dev \
|
|
lapack-dev \
|
|
# Misc compression
|
|
xz \
|
|
bzip2-dev \
|
|
# rclone (Google Drive / S3 / etc.)
|
|
rclone \
|
|
# ip / iproute2 needed by tailscaled
|
|
iproute2 \
|
|
# ── LaTeX + typesetting ───────────────────────────────────────────────────
|
|
texlive-full \
|
|
# ── Math / science CLI ────────────────────────────────────────────────────
|
|
gnuplot \
|
|
maxima \
|
|
# wxmaxima requires a display; skip in headless image
|
|
octave \
|
|
R \
|
|
&& :
|
|
|
|
# ── Typst (static binary — not in Alpine apk) ────────────────────────────────
|
|
RUN TYPST_VER=$(curl -fsSL https://api.github.com/repos/typst/typst/releases/latest \
|
|
| grep '"tag_name"' | grep -oP 'v[\d.]+') \
|
|
&& curl -fsSL "https://github.com/typst/typst/releases/download/${TYPST_VER}/typst-x86_64-unknown-linux-musl.tar.xz" \
|
|
| tar -xJ -C /tmp/ \
|
|
&& install -m 755 /tmp/typst-x86_64-unknown-linux-musl/typst /usr/local/bin/typst \
|
|
&& rm -rf /tmp/typst-x86_64-unknown-linux-musl
|
|
|
|
# ── Tailscale (static binary — userspace networking, no root required) ────────
|
|
RUN TSVER=$(curl -fsSL https://pkgs.tailscale.com/stable/ \
|
|
| grep -oP 'tailscale_\K[0-9]+\.[0-9]+\.[0-9]+(?=_amd64\.tgz)' \
|
|
| sort -V | tail -1) \
|
|
&& curl -fsSL "https://pkgs.tailscale.com/stable/tailscale_${TSVER}_amd64.tgz" \
|
|
| tar -xz -C /tmp/ \
|
|
&& install -m 755 /tmp/tailscale_${TSVER}_amd64/tailscale /usr/local/bin/tailscale \
|
|
&& install -m 755 /tmp/tailscale_${TSVER}_amd64/tailscaled /usr/local/bin/tailscaled \
|
|
&& rm -rf /tmp/tailscale_${TSVER}_amd64
|
|
|
|
# ── uv package manager ────────────────────────────────────────────────────────
|
|
RUN pipx install uv && cp /root/.local/bin/uv /usr/local/bin/uv && cp /root/.local/bin/uvx /usr/local/bin/uvx
|
|
|
|
# ── Non-root developer user 'researcher' (UID 1000) ──────────────────────────
|
|
RUN adduser -D -u 1000 researcher
|
|
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
XDG_CACHE_HOME=/home/researcher/.cache \
|
|
UV_LINK_MODE=copy
|
|
|
|
USER researcher
|
|
WORKDIR /home/researcher/stack
|
|
|
|
# ── Python 3.11 venv + all repo-required packages ────────────────────────────
|
|
RUN uv python install 3.11.15 \
|
|
&& uv venv --clear --python 3.11.15 /home/researcher/venv
|
|
|
|
# Core infrastructure / ingestion dependencies
|
|
RUN uv pip install --python /home/researcher/venv/bin/python3 \
|
|
# AWS + RDS IAM auth
|
|
boto3 \
|
|
botocore \
|
|
# Postgres
|
|
psycopg2-binary \
|
|
# HTTP clients
|
|
requests \
|
|
httpx \
|
|
# API server (swarm API, credential server)
|
|
fastapi \
|
|
"uvicorn[standard]" \
|
|
pydantic \
|
|
# Notion + Linear clients
|
|
notion-client \
|
|
# Data / serialisation
|
|
python-dotenv \
|
|
pyyaml \
|
|
rich \
|
|
# Science / math baseline (from requirements-optional-science.txt)
|
|
biopython \
|
|
networkx \
|
|
pycryptodome \
|
|
zstandard \
|
|
z3-solver \
|
|
PyWavelets \
|
|
# galois>=0.4 needs numba->llvmlite which requires LLVM; install separately on host if needed
|
|
# Numerics
|
|
numpy \
|
|
scipy \
|
|
# Arbitrary-precision arithmetic
|
|
mpmath \
|
|
# Plotting / visualisation
|
|
matplotlib \
|
|
seaborn \
|
|
# Data frames
|
|
pandas \
|
|
polars \
|
|
# Machine learning
|
|
scikit-learn \
|
|
# Search / web
|
|
beautifulsoup4 \
|
|
lxml \
|
|
# Lean / symbolic
|
|
sympy \
|
|
# Testing
|
|
pytest \
|
|
&& :
|
|
|
|
# ── elan (Lean 4 Version Manager) ────────────────────────────────────────────
|
|
RUN curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf \
|
|
| sh -s -- -y --default-toolchain leanprover/lean4:stable
|
|
|
|
# ── PATH ──────────────────────────────────────────────────────────────────────
|
|
ENV PATH="/home/researcher/.elan/bin:/home/researcher/venv/bin:/home/researcher/.local/bin:${PATH}"
|
|
|
|
# ── Tailscale userspace auto-start snippet (written as researcher) ────────────
|
|
RUN mkdir -p /home/researcher/.local/share/tailscale && \
|
|
printf '%s\n' \
|
|
'# ── Tailscale (userspace, no root required) ─────────────────────────────' \
|
|
'export TAILSCALE_SOCKET=/home/researcher/.local/share/tailscale/tailscaled.sock' \
|
|
'alias tailscale="tailscale --socket=$TAILSCALE_SOCKET"' \
|
|
'_ts_start() {' \
|
|
' if ! /usr/local/bin/tailscale --socket=$TAILSCALE_SOCKET status &>/dev/null; then' \
|
|
' mkdir -p /home/researcher/.local/share/tailscale' \
|
|
' /usr/local/bin/tailscaled \\' \
|
|
' --tun=userspace-networking \\' \
|
|
' --socket=$TAILSCALE_SOCKET \\' \
|
|
' --statedir=/home/researcher/.local/share/tailscale/ \\' \
|
|
' --outbound-http-proxy-listen=localhost:1055 \\' \
|
|
' &>>/home/researcher/.local/share/tailscale/tailscaled.log &' \
|
|
' sleep 2' \
|
|
' fi' \
|
|
'}' \
|
|
'_ts_start' \
|
|
>> /home/researcher/.bashrc
|
|
|
|
# ── rclone S3 gateway init script ─────────────────────────────────────────────
|
|
COPY --chown=researcher:researcher .devcontainer/init-rclone-s3.sh /home/researcher/init-rclone-s3.sh
|
|
RUN chmod +x /home/researcher/init-rclone-s3.sh
|
|
|
|
ENTRYPOINT ["/home/researcher/init-rclone-s3.sh"]
|
|
CMD ["/bin/bash"]
|