Using Eole with Docker
Docker keeps Eole's Python and CUDA dependencies in a container. The host still needs an NVIDIA driver compatible with the image's CUDA version, Docker, and the NVIDIA Container Toolkit. Follow NVIDIA's installation and Docker runtime configuration instructions first.
Choose or build an image
Choose a tag from the published images. Release images contain the source at that release: a 0.6.0 image does not include later MTP or REINFORCE changes. For a particular checkout, run this from the repository root:
docker build -t eole:local -f docker/Dockerfile \
--build-arg TORCH_VERSION=2.10.0 \
--build-arg CUDA_VERSION=12.8.0 .
export EOLE_IMAGE=eole:local
This uses the matching Eole base image from GHCR. If that base tag is unavailable, build it locally first:
docker build \
-t ghcr.io/eole-nlp/eole-base:torch2.10.0-ubuntu24.04-cuda12.8.0 \
-f docker/Dockerfile-base \
--build-arg TORCH_VERSION=2.10.0 \
--build-arg CUDA_VERSION=12.8.0 .
The base Dockerfile installs PyTorch and FlashAttention 2.8.3, trying a community
prebuilt wheel before falling back to compilation. The full Dockerfile installs
Eole and requirements.opt.txt. Changing CUDA/PyTorch versions requires a
compatible base image and FlashAttention build. The docker/build.sh and
docker/build_base.sh scripts also push images to GHCR; use the commands above
for local builds.
For a published image, set EOLE_IMAGE to its full ghcr.io/eole-nlp/eole:TAG
name instead.
Start a GPU container
Run from your checkout. Set EOLE_MODEL_DIR to an existing host model directory:
export EOLE_MODEL_DIR=/absolute/path/to/models
docker run --name eole-dev -it --gpus all --shm-size=8g \
-v "$EOLE_MODEL_DIR:/models" \
-v "$PWD:/workspace" \
-w /workspace \
-e EOLE_MODEL_DIR=/models \
-p 127.0.0.1:5000:5000 \
--entrypoint /bin/bash "$EOLE_IMAGE"
The checkout is mounted at /workspace, and models at /models. Use these
container paths in YAML, not host paths. Mounted output files survive container
removal; files elsewhere remain in this container until it is removed. The image
runs as root by default, so newly created mounted files can be owned by root.
The shared-memory allocation can be adjusted for training data workers.
Inside the container, check GPU access and install the mounted checkout:
nvidia-smi
python -c 'import torch; print(torch.__version__, torch.cuda.is_available())'
python -m pip install "setuptools<69" wheel packaging ninja psutil
MAX_JOBS=2 python -m pip install -e /workspace --no-build-isolation
python -c 'from eole import _ops; print("Eole CUDA extension loaded")'
A normal docker build does not expose the GPU. Eole's current setup.py skips
its CUDA extension when torch.cuda.is_available() is false, even when nvcc is
installed. The installation above builds it with the GPU visible. Alternatively,
for direct script use, run MAX_JOBS=2 python setup.py build_ext --inplace from
/workspace. Rebuild when changing GPU architecture, PyTorch, or CUDA.
For Qwen gated-delta models, check the additional kernel imports:
python -m pip install fla-core
python -c 'from flash_attn import flash_attn_func, flash_attn_with_kvcache'
python -c 'from fla.ops.gated_delta_rule import chunk_gated_delta_rule, fused_recurrent_gated_delta_rule'
See the installation instructions for FlashAttention
source installation and optional causal-conv1d. Successful imports do not prove
that every kernel executes on your GPU.
Run inference or serve with YAML
Inside the container, use the same YAML recipes as a native installation. For a converted Qwen3.8 checkpoint stored in the mounted model directory:
export QWEN38_MODEL=/models/Qwen3.8-27B-INT4
python -m eole.bin.main predict -c recipes/qwen38/predict.yaml
python -m eole.bin.main serve -c recipes/qwen38/serve.yaml \
--host 0.0.0.0 --port 5000
The server must bind to 0.0.0.0 inside the container for Docker port forwarding.
The example publishes only to the host's loopback address. From a host terminal:
curl http://127.0.0.1:5000/health
curl http://127.0.0.1:5000/v1/models
See the Qwen3.8 recipe for checkpoint conversion,
MTP requirements, and validation, the server recipe
for API examples, and the Claude Code recipe
for connecting a host client to the endpoint. Training works the same way:
python -m eole.bin.main train -c /workspace/path/to/train.yaml, with datasets and
checkpoint output directories on mounted storage.
Exit the shell to stop the container, then resume it with docker start -ai eole-dev. To discard its container-local changes, use docker rm eole-dev after
stopping it. A new container needs the runtime kernel build again unless those
artifacts are retained in the mounted checkout or baked into a separately saved
image.