#!/bin/sh # Build and push one service's image, inside limits Tower can afford. # # sh scripts/build-image.sh ipx|directory|play|web|coverage # # On 2026-11-04 a plain `docker buildx build` of ipx (its dependencies' cache layer invalidated # by a Cargo.toml change) rebuilt everything in release on all twelve threads with 5 GB free and # no swap; Tower thrashed for three hours with every core pegged and had to be rebooted. So the # build runs in a BuildKit container under a cgroup cap: past the memory cap the build is killed, # it does not take production down with it. And it does not start without room for that cap. set -eu MEM=6g # the builder's memory cap (Tower has no swap to spill into) CPUS=0-5 # six of twelve threads; cargo inside sees six and runs six jobs NEED_KB=$((9 * 1024 * 1024)) # the cap plus 3 GB for everything else MAX_LOAD=12 BUILDER=ipx-capped case "${1:-}" in ipx) FILE=Dockerfile; IMAGE=ipx ;; directory) FILE=Dockerfile.directory; IMAGE=ipx-directory ;; play) FILE=Dockerfile.play; IMAGE=ipx-play ;; web) FILE=Dockerfile.web; IMAGE=ipx-web ;; # Not a service: what scripts/coverage.sh runs the Rust tests in (#390). coverage) FILE=Dockerfile.coverage; IMAGE=ipx-coverage ;; *) echo "usage: $0 ipx|directory|play|web|coverage" >&2; exit 2 ;; esac cd "$(dirname "$0")/.." avail=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo) load=$(cut -d' ' -f1 /proc/loadavg) echo "MemAvailable $((avail / 1024)) MB, load $load" if [ "$avail" -lt "$NEED_KB" ]; then echo "refusing: under $((NEED_KB / 1024 / 1024)) GB available. Wait, or find what is using it." >&2 exit 1 fi if awk -v l="$load" -v m="$MAX_LOAD" 'BEGIN { exit !(l > m) }'; then echo "refusing: load over $MAX_LOAD. Wait for it to come down." >&2 exit 1 fi # Made once; buildx starts its container again when needed, after a reboot too. if ! docker buildx inspect "$BUILDER" >/dev/null 2>&1; then docker buildx create --name "$BUILDER" --driver docker-container \ --driver-opt "memory=$MEM,cpuset-cpus=$CPUS" \ --buildkitd-config scripts/buildkitd.toml >/dev/null fi exec docker buildx build --builder "$BUILDER" -f "$FILE" \ --tag "192.168.1.130:5000/$IMAGE:latest" --push .