# The matching lock records the tag provenance, platform, Python, PyTorch, # CUDA, and cuDNN compatibility. Never replace this with a mutable tag. ARG BASE_IMAGE=docker.io/pytorch/pytorch@sha256:639b8229ccfd8a3aa803cf49c33d6d6fe406750d79aaf723fe8c0eb1060d8cff FROM ${BASE_IMAGE} ARG BASE_IMAGE ARG PYTHON_VERSION=3.11 LABEL org.opencontainers.image.title="jr-wakeword-training" \ org.opencontainers.image.description="Offline LiveKit WakeWord 0.2.1 training lane" \ org.opencontainers.image.source="https://github.com/livekit/livekit-wakeword" \ org.opencontainers.image.revision="1ec7f680df30ff4ca0ebae6b5983441e94b10980" \ org.opencontainers.image.version="0.2.1" ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ NLTK_DATA=/usr/local/share/nltk_data RUN case "${BASE_IMAGE}" in *@sha256:*) ;; *) echo "BASE_IMAGE must be digest-pinned" >&2; exit 64;; esac \ && apt-get update \ && apt-get install -y --no-install-recommends espeak-ng libsndfile1 ffmpeg sox time \ && rm -rf /var/lib/apt/lists/* \ && python -c "import sys; assert sys.version_info[:2] == (${PYTHON_VERSION%.*}, ${PYTHON_VERSION#*.})" WORKDIR /opt/jr-wakeword # The complete hash lock is generated with uv and reviewed in source control. # Network access is permitted only at image build time; a launched training # container is network-isolated and never resolves or installs dependencies. COPY deploy/wakeword-training/requirements.wheelhouse.lock ./requirements.wheelhouse.lock RUN python -m pip install --require-hashes -r requirements.wheelhouse.lock \ && python -c "from importlib.metadata import version; assert version('livekit-wakeword') == '0.2.1'; assert version('torch') == version('torchaudio')" \ && python -c "import nltk; assert nltk.download('cmudict', download_dir='/usr/local/share/nltk_data', quiet=True, raise_on_error=True)" COPY scripts/wakeword_training_image.py ./wakeword_training_image.py COPY deploy/wakeword-training/run-commercial-pipeline.py ./run-commercial-pipeline.py COPY deploy/wakeword-training/run-local-experiment.py ./run-local-experiment.py COPY deploy/wakeword-training/run-quarantined-smoke.py ./run-quarantined-smoke.py COPY deploy/wakeword-training/stage_evidence.py ./stage_evidence.py COPY deploy/wakeword-training/record-image-provenance.py ./record-image-provenance.py COPY deploy/wakeword-training/finalize-run.py ./finalize-run.py # Do not add listener extras, microphone SDK packages, gateway source, gateway credentials, # Docker socket access, or published ports in this one-shot image. # DockerTrainingExecutor supplies the explicit commercial/quarantined wrapper # as argv. CMD keeps that argv from being appended to a fixed ENTRYPOINT. CMD ["python", "/opt/jr-wakeword/run-commercial-pipeline.py", "/run/resolved-config.yaml"]