# Web Applications workspace image: Rust (Tauri 2 / gRPC), Bun + Node/pnpm, # Python + CV/ONNX prototyping, and DB CLI clients baked in at build time so # workspace start doesn't pay for a from-scratch toolchain install. # # Built by templates/web/main.tf via the docker provider's `build` block # (context = this directory), not pulled from a registry. FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ locales sudo ca-certificates gnupg curl wget \ && locale-gen en_US.UTF-8 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* ENV LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 # Google Chrome (stable), for the Browse Lite VS Code extension's embedded # browser preview. Ubuntu's own `chromium-browser` apt package is just a # snap wrapper and doesn't work in a container (no snapd) - Google's own # .deb is the reliable way to get a real Chrome binary here. amd64 only # (Google doesn't publish a Chrome .deb for arm64), which matches this # repo's single x86_64 Docker host. RUN curl -fsSL https://dl.google.com/linux/linux_signing_key.pub \ | gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg \ && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \ > /etc/apt/sources.list.d/google-chrome.list \ && apt-get update && apt-get install -y google-chrome-stable \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* # Core build toolchain, crypto/DB headers, Tauri 2 / WebKit GUI prerequisites, # X11 dev libs, DB CLI clients, Python + OpenCV, protobuf compiler. # # Split into several RUN steps (rather than one big apt-get install) so no # single resulting layer is too large to push to the registry - it sits # behind a reverse proxy with a request body size cap, and a couple of these # packages (llvm, libopencv-dev, libwebkit2gtk-4.1-dev) are individually # large enough to blow past it if lumped together with everything else. RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential pkg-config cmake \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ clang llvm \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ git git-lfs jq unzip tar file htop tree tmux zsh openssh-client \ && git lfs install --system \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev libpq-dev libsqlite3-dev \ postgresql-client redis-tools sqlite3 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libxdo-dev \ libgtk-3-dev libsoup-3.0-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ libx11-dev libxext-dev libxrender-dev libxtst-dev libxi-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip python3-venv python3-dev \ protobuf-compiler \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN apt-get update && apt-get install -y --no-install-recommends \ libopencv-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* # Node.js LTS (22.x) plus npm/pnpm/yarn as root so global bins land on the # system PATH for every user. RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* RUN npm install -g pnpm yarn # Global Python prototyping packages: CV, ONNX runtime, CPU-only torch wheel. # Ubuntu 24.04's system Python is PEP 668 externally-managed; this is a # throwaway container image, so --break-system-packages is the right call # instead of forcing every user into a venv for basic prototyping. Not # upgrading pip itself first: the Debian-packaged pip 24.0 has no RECORD # file (dpkg-installed, not pip-installed), so `pip install --upgrade pip` # fails trying to uninstall it in place - and it's unneeded anyway, the # packages below install fine under the stock version. # # Each package gets its own RUN/layer for the same reverse-proxy body-size # reason as the apt-get split above - torch's CPU wheel and opencv-python's # wheel are each large enough on their own to be worth isolating. RUN python3 -m pip install --break-system-packages --no-cache-dir numpy RUN python3 -m pip install --break-system-packages --no-cache-dir opencv-python-headless RUN python3 -m pip install --break-system-packages --no-cache-dir onnxruntime RUN python3 -m pip install --break-system-packages --no-cache-dir \ torch --index-url https://download.pytorch.org/whl/cpu # Standard non-root dev user with passwordless sudo. Ubuntu 24.04's base # image already ships a default `ubuntu` user/group at uid/gid 1000, which # collides with the explicit --uid 1000 below - drop it first so `coder` # can take that uid. RUN userdel -r ubuntu 2>/dev/null; \ groupdel ubuntu 2>/dev/null; \ useradd --uid 1000 --create-home --shell /bin/bash coder \ && echo "coder ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/coder \ && chmod 0440 /etc/sudoers.d/coder ENV RUST_BACKTRACE=1 \ RUSTUP_HOME=/home/coder/.rustup \ CARGO_HOME=/home/coder/.cargo \ BUN_INSTALL=/home/coder/.bun \ PNPM_HOME=/home/coder/.local/share/pnpm \ PATH=/home/coder/.cargo/bin:/home/coder/.bun/bin:/home/coder/.local/share/pnpm:/home/coder/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin USER coder WORKDIR /home/coder # Rust via rustup: stable toolchain, rust-analyzer/clippy/rustfmt/rust-src, # native + musl targets for x86_64/aarch64, and cargo helper utilities. # # Split into one RUN per target/tool (rather than one big chained command) so # no single layer is too large to push to the registry, for the same # reverse-proxy body-size reason as the apt-get split above - the base # toolchain and each additional target's std library are each sizeable, and # `cargo install` leaves a build/registry cache behind that needs clearing # inside its own RUN, or it would just bloat that same layer instead. RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ --default-toolchain stable --profile default \ && rm -rf "$RUSTUP_HOME"/tmp "$RUSTUP_HOME"/downloads RUN rustup component add rustfmt clippy rust-analyzer rust-src RUN rustup target add x86_64-unknown-linux-gnu RUN rustup target add x86_64-unknown-linux-musl RUN rustup target add aarch64-unknown-linux-gnu RUN rustup target add aarch64-unknown-linux-musl RUN cargo install --locked cargo-watch \ && rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git RUN cargo install --locked cargo-edit \ && rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git RUN cargo install --locked cross \ && rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git RUN cargo install --locked bacon \ && rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git # Bun: global runtime for the ElysiaJS backend and fast scripting. RUN curl -fsSL https://bun.sh/install | bash RUN mkdir -p /home/coder/workspace WORKDIR /home/coder/workspace