OpenCascade.js

Docker image

GHCR image tags, multi-arch matrix, OCI labels, cosign signatures, provenance, and SBOM.

The maintainer-distributed Docker image lets consumers run custom-trimmed wasm builds without setting up emsdk, libclang, and Python locally.

Pulling

docker pull ghcr.io/taucad/opencascade.js:single-threaded

Tags

TagPoints to
:single-threadedLatest release, single-threaded warm cache (default for browser CAD UIs)
:multi-threadedLatest release, multi-threaded warm cache (requires COOP/COEP on consumer pages)
:bindgen-baseLatest release, post-PCH/generate but pre-compile (custom-bindings starting point)
:{{version}}-single-threaded
:{{version}}-multi-threaded
Pinned release (e.g. :3.0.0-single-threaded); manifest list of linux/amd64+arm64
:{{version}}-bindgen-basePinned release, bindgen-base
:branch-<slug> / :branch-<slug>-<sha>Branch tip, single-threaded, linux/amd64-only, 7-day GHCR retention
:multi-threaded-branch-<slug> / …-<sha>Branch tip, multi-threaded, amd64-only, 7-day retention
:bindgen-base-branch-<slug> / …-<sha>Branch tip, bindgen-base, amd64-only, 7-day retention
@sha256:<digest>Immutable pin — use in CI

Pin by digest in production. The bare-name tags (:single-threaded, :multi-threaded, :bindgen-base) are mutable and roll forward with every release. See Reproducible CI for the pinning workflow.

The legacy :beta, :rolling, and :latest tags are not published by this fork. Use a version-pinned tag (e.g. :3.0.0-single-threaded) or the manifest-list digest for explicit version control.

Entrypoint

docker run --rm \
  -v "$(pwd):/src" \
  -u "$(id -u):$(id -g)" \
  ghcr.io/taucad/opencascade.js:single-threaded \
  link mybuild.yml

The entrypoint dispatches subcommands through npx nx run ocjs:<target> so runs benefit from Nx's content-addressed cache:

SubcommandWhat it does
link <yaml>End-to-end build. Nx walks apply-patches → pch → generate → compile-bindings → compile-sources → link with cache reuse — fresh container = full build, cached re-run = link only.
compile-bindings, compile-sources, pch, …Run an individual Nx target
validate <yaml>Validate YAML without building
nx <args…>Pass-through to npx nx (escape hatch)

Outputs land in /src next to your YAML (OCJS_OUTPUT_DIR=/src default).

Override the entrypoint

docker run --rm -it -v "$(pwd):/src" --entrypoint bash \
  ghcr.io/taucad/opencascade.js:single-threaded

…drops you into a shell with emsdk, libclang, and Python on the PATH.

Multi-arch matrix

Tag familyManifest listBuilt on
Release tagslinux/amd64 + linux/arm64ubuntu-latest (amd64) + ubuntu-24.04-arm (arm64), GitHub Actions native runners
Branch tagslinux/amd64 onlyubuntu-latest, GitHub Actions

Releases ship full manifest lists so Apple Silicon and ARM Linux hosts pull the native arch transparently. Branch tags are amd64-only by design (R12 in the production-readiness blueprint) — ARM hosts will run under Rosetta / QEMU for branch tags.

OCI labels

Inspect via docker inspect ghcr.io/taucad/opencascade.js:single-threaded:

LabelPurpose
org.opencontainers.image.titleStage-specific title (single-threaded, multi-threaded, …)
org.opencontainers.image.descriptionThreading model and consumer prerequisites
org.opencontainers.image.sourcehttps://github.com/taucad/opencascade.js
org.opencontainers.image.urlSame as source
org.opencontainers.image.revisionGit commit the image was built from
org.opencontainers.image.versionSemver tag
org.opencontainers.image.licensesLGPL-2.1-only
org.opencontainers.image.vendortaucad

Cosign signatures

Every published image is signed with cosign via OIDC keyless signing — no rotating private keys, signatures published to the Sigstore Rekor transparency log. Release tags carry one signature on the manifest-list digest that verifies regardless of which arch the consumer pulls; branch tags carry per-arch image-digest signatures.

cosign verify ghcr.io/taucad/opencascade.js:single-threaded \
  --certificate-identity-regexp 'https://github.com/taucad/opencascade\.js/\.github/workflows/docker\.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

A successful verification confirms the image was built by the taucad/opencascade.js GitHub Actions docker.yml workflow and has not been tampered with since publication.

Provenance

cosign verify-attestation \
  --type slsaprovenance \
  --certificate-identity-regexp 'https://github\.com/taucad/opencascade\.js/\.github/workflows/docker\.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/taucad/opencascade.js:single-threaded

The attestation records the source commit, the workflow, and the runner that produced the image.

SBOM

docker buildx imagetools inspect \
  --format '{{ json .SBOM }}' \
  ghcr.io/taucad/opencascade.js:single-threaded

Diff the SBOM across image digests in CI to flag unexpected dep bumps.

Image stages

The Dockerfile is multi-stage with five logical stages, three of which are published:

StagePublished asContents
deps-base(not published)emsdk + apt + Node 24 + uv + Python + OCCT/rapidjson/freetype + LLVM 17 headers
bindgen-base:bindgen-basedeps + npm ci + patches + PCH + .d.ts.json index
compiled-single-threaded(not published)bindgen + compiled .o files + OCCT .a (single-threaded)
compiled-multi-threaded(not published)bindgen + compiled .o files + OCCT .a (multi-threaded)
final-single:single-threadedcompiled-single + OCI labels + entrypoint
final-multi:multi-threadedcompiled-multi + OCI labels + entrypoint

Each stage is independently rebuildable via docker buildx build --target <stage>. See Bindgen pipeline for how the stages compose with the build pipeline.

On this page