(!) NOT OFFICIAL = not recommended unless you know what you are doing.
What — Unofficial EIC containers built from clean source with debug symbols enabled.
Compatibility with EIC — Partial. Package versions track the official EIC spack environment but are not guaranteed to stay in sync.
What this is NOT — A full-featured rewrite of eic-shell / eicweb/eic_xl. Many tools are not installed.
Why — Easy for IDEs and other tooling (no spack links trickery), easy to plug and customize ANY part of the chain, easy to customize overall. Philosophy: clone+cmake+install one by one. No spack, no software hidden over links in links after links, no hidden layers of configuration that is invoked or not depending on containers flags.
graph TD
B["<b>eicdev/ubuntu-root</b><br/>Clang 18 · CERN ROOT 6.38 · XRootD<br/>cmake, gdb, ninja... &such"]
C["<b>eicdev/eic-base</b><br/>fmt · CLHEP · Eigen3 · FastJet · HepMC3<br/>Geant4 · PODIO · EDM4hep · EDM4eic<br/>DD4hep · ACTS · JANA2 · IRT · Algorithms"]
D["<b>eicdev/eic-full</b><br/>EPIC(dd4hep) + EICrecon"]
E["<b>eicdev/eic-claude</b> 🤖<br/>Node.js + Claude Code agent<br/>semi-auto / autonomous"]
G["<b>eicdev/eic-gemini</b> ♊<br/>Node.js + Gemini CLI agent<br/>semi-auto / autonomous"]
F["<b>eicdev/meson-structure</b> ⚗️<br/>Experimental — EDPM-based subset"]
B --> C
C --> D
D --> E
D --> G
B -.->|experimental| F
| Image | Based on | Adds |
|---|---|---|
eicdev/ubuntu-root |
ubuntu:24.04 |
Clang 18, CERN ROOT 6.38, XRootD, build tools, debug tooling |
eicdev/eic-base |
ubuntu-root |
EIC dependency stack (see package list) |
eicdev/eic-full |
eic-base |
EPIC detector geometry, EICrecon reconstruction framework |
eicdev/eic-extra |
eic-full |
Rucio client + EIC storage policy for data access at JLab |
eicdev/eic-claude |
eic-full |
Node.js + Claude Code CLI, pre-configured for semi-automatic / autonomous agent runs |
eicdev/eic-gemini |
eic-full |
Node.js + Gemini CLI, pre-configured for semi-automatic / autonomous agent runs |
eicdev/meson-structure |
ubuntu-root |
Experimental EDPM-based build (not part of main chain) |
# Minimal: ROOT + build tools only
docker pull eicdev/ubuntu-root:latest
docker run --rm -it eicdev/ubuntu-root:latest
# Full EIC dependency stack (no detector geometry)
docker pull eicdev/eic-base:latest
docker run --rm -it eicdev/eic-base:latest
# With EPIC geometry and EICrecon
docker pull eicdev/eic-full:latest
docker run --rm -it eicdev/eic-full:latest
# With Rucio data access (JLab storage)
docker pull eicdev/eic-extra:latest
docker run --rm -it eicdev/eic-extra:latest
# With the Claude Code agent (full stack + Node.js + Claude Code CLI)
docker pull eicdev/eic-claude:latest
docker run --rm -it -e ANTHROPIC_API_KEY=sk-ant-... eicdev/eic-claude:latest claude
# With the Gemini CLI agent (full stack + Node.js + Gemini CLI)
docker pull eicdev/eic-gemini:latest
docker run --rm -it -e GEMINI_API_KEY=AIzaSy... eicdev/eic-gemini:latest gemini# Mount local code at /work inside the container
docker run --rm -it \
-v /path/to/your/repo:/work \
eicdev/eic-base:latest
# Inside the container — standard CMake workflow:
cd /work
cmake -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build -j$(nproc)The images are designed for use with IDE remote/container plugins (VS Code Dev Containers, CLion remote, etc.). All packages are installed under /app/<package> and added to CMAKE_PREFIX_PATH, so CMake finds them automatically.
VS Code Dev Containers — add a .devcontainer/devcontainer.json to your project:
{
"image": "eicdev/eic-base:latest",
"mounts": ["source=${localWorkspaceFolder},target=/work,type=bind"],
"workspaceFolder": "/work"
}CLion — use Settings → Build → Docker and point to eicdev/eic-base:latest (or eic-full if you need EPIC/EICrecon).
All environment variables are set in the image. After entering a shell, ROOT, DD4hep, ACTS, JANA2, etc. are all ready:
root --version # CERN ROOT
ddsim --help # DD4hep simulation
jana -l # JANA2 plugin list
eicrecon --help # EICrecon (eic-full and above only)The eic-extra image includes a pre-configured Rucio client pointed at rucio-server.jlab.org with a read-only public account (eicread). No extra setup is needed for read access:
rucio list-dids eic:*
rucio download eic:<dataset>The eic-claude image adds Node.js and the Claude Code CLI on top of the full EIC stack, so the agent can build, run, and debug EIC software with the whole toolchain already present. Supply your Anthropic key via ANTHROPIC_API_KEY (or mount an existing ~/.claude login) and mount your source tree at /work.
# Interactive agent session
docker run --rm -it --init \
-e ANTHROPIC_API_KEY=sk-ant-... \
-v "$PWD":/work -w /work \
eicdev/eic-claude:latest claude
# Semi-automatic: edits auto-accepted, shell commands still prompt (the baked-in default)
docker run --rm -it --init -e ANTHROPIC_API_KEY=sk-ant-... \
-v "$PWD":/work -w /work eicdev/eic-claude:latest \
claude "fix the failing EICrecon test"
# Fully autonomous / headless: no prompts at all
docker run --rm --init -e ANTHROPIC_API_KEY=sk-ant-... \
-v "$PWD":/work -w /work eicdev/eic-claude:latest \
claude -p "build epic and report any errors" --dangerously-skip-permissionsAgent behaviour is controlled by three things:
settings.json(baked at/root/.claude/settings.json) setspermissions.defaultModetoacceptEdits— the semi-automatic default. Override it by mounting your own settings or passing--permission-mode.--dangerously-skip-permissionson the command line disables all prompts for fully autonomous runs.IS_SANDBOX=1is baked into the image so this works while running as root inside the container.DISABLE_AUTOUPDATER=1pins the CLI to the version baked into the image for reproducible runs.
⚠️ Autonomous mode grants the agent unrestricted shell access inside the container. Only use it against source you trust and, ideally, without mounting sensitive host paths.
The eic-gemini image adds Node.js and the @google/gemini-cli CLI on top of the full EIC stack, so Gemini can build, run, and debug EIC software with the complete toolchain and Python environment available. Supply your Gemini API key via GEMINI_API_KEY (or mount an existing ~/.gemini directory) and mount your source tree at /work.
# Interactive agent session
docker run --rm -it --init \
-e GEMINI_API_KEY=AIzaSy... \
-v "$PWD":/work -w /work \
eicdev/eic-gemini:latest gemini
# Semi-automatic: edits auto-accepted, shell commands still prompt (the baked-in default)
docker run --rm -it --init -e GEMINI_API_KEY=AIzaSy... \
-v "$PWD":/work -w /work eicdev/eic-gemini:latest \
gemini -p "fix the failing EICrecon test"
# Fully autonomous / headless: YOLO mode (no confirmation prompts)
docker run --rm --init -e GEMINI_API_KEY=AIzaSy... \
-v "$PWD":/work -w /work eicdev/eic-gemini:latest \
gemini --yolo -p "build epic and report any errors"Agent behaviour is controlled by:
settings.json(baked at/root/.gemini/settings.jsonand/etc/gemini-cli/settings.json) setsgeneral.defaultApprovalModetoauto_edit— the semi-automatic default.--yolo(or--approval-mode=yolo) on the command line auto-approves all tool executions for fully autonomous runs.IS_SANDBOX=1is baked into the image.
⚠️ Autonomous YOLO mode grants the agent unrestricted shell and filesystem access inside the container. Only run against trusted source code.
| Package | Version | Notes |
|---|---|---|
| CERN ROOT | 6.38.00 | Built from source, debug symbols on |
| fmt | 11.2.0 | Built from source — Ubuntu ships 10.1.1, PODIO requires 11+ |
| CLHEP | 2.4.7.1 | |
| Eigen3 | 3.4.0 | |
| Catch2 | 3.8.1 | |
| FastJet | 3.5.0 + contrib 1.102 | |
| HepMC3 | 3.3.0 | |
| Geant4 | 11.3.2 | |
| PODIO | v01-06 | |
| VGM | 5.3.1 | |
| EDM4HEP | v00-99-04 | |
| EDM4EIC | v8.8.0 | |
| DD4hep | v01-36 | |
| ActsSVG | v0.4.56 | |
| OnnxRuntime | 1.17.0 | Prebuilt CPU-only binary |
| ACTS | v44.4.0 | |
| JANA2 | v2.4.3 | |
| IRT | v1.0.10 | Installed at /app/irt, exports CMake package IRT (for EICrecon) |
| IRT2 | v2.1.1 | Installed at /app/irt2, exports CMake package IRT2 (for epic) |
| Algorithms | v1.2.0 | |
| spdlog | v1.17.0 | Built from source for fmt 11 ABI compatibility |
| Package | Version |
|---|---|
| EPIC | main |
| EICrecon | main |
Why some packages are built from source instead of apt:
fmt: Ubuntu 24.04 ships v10.1.1; PODIO requiresfmt::println(FILE*,...)from v11.spdlog: Ubuntu's package is compiled against fmt 10, ABI-incompatible with fmt 11.nlohmann/json: Built separately (v3.11.3) so all packages share the same ABI namespace; the system copy conflicts with ACTS's bundled copy.ROOT: Needs debug symbols and specific feature flags (-Droot7,-Dgdml,-Dxrootd).
- Docker with BuildKit support (Docker 23+)
- 30+ GB disk space per full build
- Adequate RAM (16 GB minimum, 32 GB recommended for parallel builds)
Builds the chain sequentially, streams live output, and prints a summary table.
# Build all images (auto-detects CPU count)
python3 build_images.py
# Build with 24 threads, push to registry
python3 build_images.py --no-cache --push -j 24
# Build only eic-base and its dependencies
python3 build_images.py ubuntu-root eic-base
# Custom tag (also tag as :latest)
python3 build_images.py --tag v1.0 --latest --push
# Dry run — print commands without executing
python3 build_images.py --dry-runUses docker-bake.hcl. The contexts blocks wire FROM dependencies at the BuildKit level. Requires the docker-container driver (one-time setup):
docker buildx create --name eic-builder --driver docker-container --use# Build + push all images
docker buildx bake -f docker-bake.hcl --push
# Build one target (its dependencies build first automatically)
docker buildx bake -f docker-bake.hcl --push eic-base
# No-cache rebuild
docker buildx bake -f docker-bake.hcl --no-cache --push
# Dry run — print resolved config as JSON, build nothing
docker buildx bake -f docker-bake.hcl --print
# Custom threads + tag
BUILD_THREADS=24 IMAGE_TAG=v1.0 docker buildx bake -f docker-bake.hcl --pushThe
docker-containerdriver does not support--load. Use--pushto push to a registry, or usebuild_images.pyfor local builds.
docker buildx build --tag eicdev/ubuntu-root:latest --build-arg BUILD_THREADS=24 ubuntu-root/
docker buildx build --tag eicdev/eic-base:latest --build-arg BUILD_THREADS=24 eic-base/
docker buildx build --tag eicdev/eic-full:latest --build-arg BUILD_THREADS=24 eic-full/
docker buildx build --tag eicdev/eic-extra:latest --build-arg BUILD_THREADS=24 eic-extra/
docker buildx build --tag eicdev/eic-claude:latest --build-arg BUILD_THREADS=24 eic-claude/
docker buildx build --tag eicdev/eic-gemini:latest --build-arg BUILD_THREADS=24 eic-gemini/| Argument | Default | Description |
|---|---|---|
BUILD_THREADS |
8 |
Parallel make/cmake jobs (-j) |
CXX_STANDARD |
20 |
C++ standard for all packages |
IMAGE_TAG |
latest |
Image tag (bake only) |
Individual package versions can be overridden with VERSION_* build args (e.g. VERSION_ACTS, VERSION_GEANT4). Defaults match the official EIC spack environment.
$env:BUILD_THREADS = "24"
python3 build_images.py --push
# Or with bake
$env:BUILD_THREADS = "24"; $env:IMAGE_TAG = "v1.0"
docker buildx bake -f docker-bake.hcl --push
# Clean up
Remove-Item Env:\BUILD_THREADS, Env:\IMAGE_TAG# Drop into a bash shell at the failing layer (Linux/macOS)
BUILDX_EXPERIMENTAL=1 docker buildx debug --invoke bash build \
--progress=plain -f eic-base/Dockerfile eic-base/
# PowerShell
$env:BUILDX_EXPERIMENTAL = "1"
docker buildx debug --invoke bash build --progress=plain -f eic-base/Dockerfile eic-base/