Commit Graph

4 Commits

Author SHA1 Message Date
sboddy 6dec340161 Merge pull request #8576 from IfcOpenShell/fix/docker-macos-arm64-compat
docker: more robust in getting a GID, and editing the .env file.
2026-07-13 13:09:29 +01:00
Stephen Boddy b1470223d3 Share ccache volume across checkouts, cap at 2G
The ccache named volume had no explicit name, so Docker Compose
namespaced it under the per-checkout project name (derived from
UNIQUE_ID), giving each checkout its own cache even though
docker/README.md already documented them as shared. Give the volume
a fixed name so all checkouts attach the same one.

Measured cache size after a full build (IfcParse+IfcGeom+IfcConvert+
wrapper, one Python version) is ~300MB, only ~5% of the previous 5G
cap. Shrink CCACHE_MAXSIZE to 2G, which comfortably covers the shared
baseline plus per-branch deltas from several diverging checkouts.

Generated with the assistance of an AI coding tool.
2026-07-13 06:42:05 +01:00
Petru Conduraru f25b072fa0 docker: make the build env work on macOS / Apple Silicon hosts
Three host-portability fixes to the docker/ toolchain from #8564 so it
runs on macOS as well as Linux. All three are no-ops on native amd64
Linux.

1. Dockerfile: only groupadd when the target GID is free. macOS's default
   primary group `staff` is GID 20, which already exists as `games` in
   rockylinux:9, so `groupadd -g 20` aborted the image build. Guard with
   `getent group "${USER_GID}" || groupadd ...`; useradd -g accepts the
   existing GID.

2. ifcos_env unique(): replace GNU-only `sed -si` (BSD/macOS sed errors
   "illegal option -- s") with a portable `sed > tmp && mv` rewrite of the
   UNIQUE_ID line. Verified against macOS BSD sed.

3. create() + compose.yaml: build with an explicit `--platform linux/amd64`
   so the locally built image's platform matches the `platform:
   linux/amd64` pin in compose.yaml. Without it, on arm64 the local image
   is tagged linux/arm64, compose treats the platform-mismatched image as
   absent and tries to pull `ifcopenshell-build-env:updated` from Docker
   Hub (which does not exist -> access denied). Also add `pull_policy:
   never` as a safety net so a future mismatch surfaces as a clear "image
   not found" rather than a registry auth error.

Note: on Apple Silicon the amd64 build runs under emulation and a cold
full build is slow; ccache makes incremental rebuilds tolerable. A native
Linux/Intel host or CI remains the better choice for routine use, but these
fixes turn "hard broken" into "works with a caveat" on macOS.

This change was made with the assistance of an AI tool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 06:44:55 +03:00
Stephen Boddy 92c50ed3b4 Harden docker build tooling: non-root, clean lifecycle, try()
Dockerfile (renamed from Dockerfile_init, Dockerfile_update removed):
- Run as a non-root `builder` user matching the host UID/GID (passed as
  --build-arg by create() from id -u/id -g), so build output under the
  bind mount stays owned by the host user instead of root.
- Fix CCACHE_MAXSIZE: `ccache -M 5G` wrote its limit to a config file
  under /ccache at image-build time, but /ccache is a volume mount
  point, so that file gets shadowed by the (empty) volume the moment
  the container actually runs - the cap never took effect. Set
  CCACHE_MAXSIZE=5G as an image ENV instead.
- Dedupe ccache/libffi-devel, add --setopt=install_weak_deps=False
  --setopt=tsflags=nodocs, add `git lfs install --system`, combine the
  dnf update+install into one layer.
- Drop Dockerfile_update: it built FROM its own previous output, so
  every `update` call made the image strictly larger forever (Docker
  layers are append-only, `dnf clean` in a later layer can't shrink an
  earlier one). `update` now just calls create(), which already runs
  `dnf update -y` FROM a clean rockylinux:9 every time.

compose.yaml: pin platform: linux/amd64 so this doesn't silently run
under emulation on an ARM host.

ifcos_env:
- Split the previously-conflated stop/down into six distinct,
  Compose-native lifecycle commands: up (create-or-start), down
  (remove), stop, start, restart (stop+start, same container),
  recreate (down+up, fresh container). Previously `stop` was aliased
  to `down`, which silently removed the container instead of pausing
  it.
- Implement try(): copies the built wrapper into a real Blender/Bonsai
  install for manual testing, reading the target from a new
  BLENDER_USER_RESOURCE .env variable and auto-detecting the built
  Python version (disambiguating via PY_TGT for multi-version builds).
  Deliberately kept human-only - it mutates a live Blender install, so
  it shouldn't run unattended as part of an automated/AI workflow,
  which should instead copy the wrapper into the repo's own
  src/ifcopenshell-python/ifcopenshell/ (documented in SKILL.md).
- Fix unique(): the "has .env already got a UNIQUE_ID line" check
  referenced an unset $FILE instead of $ENV_FILE, so it always
  evaluated true and appended a fresh "UNIQUE_ID=dummy" line to .env
  on every single `up`.
- Minor: differentiate remove()'s log message from down()'s (no longer
  identical now that they're distinct operations), tidy help text
  alignment and a stray double-space typo in clean().

SKILL.md: rewritten as current-state documentation (no more "fixed in
this copy" changelog framing) covering the above, plus a migration
note for anyone hitting root-owned leftovers from an older image.

Verified by actually building the image and driving every new
lifecycle command (stop/start/restart keep the same container ID;
down+up and recreate produce a new one) and try() (including the
quoted-tilde BLENDER_USER_RESOURCE edge case) against the real container.

Generated with the assistance of an AI coding tool.
2026-07-12 20:35:01 +01:00