Problem
When running MLflow inside a Docker container, attempts to log or retrieve audio artifacts fail with an exception similar to:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/mlflow/tracking/client.py", line 1245, in log_artifact
_upload_artifact(local_path, artifact_path, run_id, client)
File "/usr/local/lib/python3.10/site-packages/mlflow/tracking/client.py", line 1103, in _upload_artifact
_log_artifact(local_path, artifact_path, run_id, client)
File "/usr/local/lib/python3.10/site-packages/mlflow/tracking/client.py", line 1156, in _log_artifact
_log_artifact_to_artifact_repo(local_path, artifact_path, run_id, client)
File "/usr/local/lib/python3.10/site-packages/mlflow/tracking/client.py", line 1172, in _log_artifact_to_artifact_repo
mlflow.utils.file_utils.copy_file(local_path, dst_path)
File "/usr/local/lib/python3.10/site-packages/mlflow/utils/file_utils.py", line 95, in copy_file
shutil.copyfile(src, dst)
FileNotFoundError: [Errno 2] No such file or directory: 'ffmpeg'
The failure prevents:
- Logging raw
.wav,.mp3, or.flacfiles as artifacts. - Automatic conversion of audio to a standardized format performed by MLflow’s
mlflow.audio.log_artifacthelper. - Retrieving the artifact via the UI or
mlflow.artifacts.download_artifactscall.
Root Cause
MLflow’s audio utilities rely on the external ffmpeg binary (or the ffprobe companion) to probe, transcode, and validate audio streams. Inside the container the binary is absent, or it is present but not reachable via the PATH environment variable. The missing dependency triggers a FileNotFoundError at the point where the helper invokes subprocess.run(["ffmpeg", …]). The issue is isolated to the container image; the same code runs without error on a host that has ffmpeg installed.
Debug
1. Inspect the container logs
docker logs mlflow-runner
...
mlflow.exceptions.MlflowException: Unable to locate ffmpeg binary. Ensure ffmpeg is installed and on PATH.
2. Verify binary presence
docker exec -it mlflow-runner which ffmpeg
# No output → binary not found
3. Check PATH inside the container
docker exec -it mlflow-runner echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
4. Attempt a manual invocation
docker exec -it mlflow-runner ffmpeg -version
bash: ffmpeg: command not found
5. Identify the base image used
# Dockerfile snippet (original)
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "run.py"]
The python:3.10-slim image does not ship with multimedia libraries.
Solution
Install ffmpeg (and its runtime dependencies) in the Docker image and ensure the binary is on PATH. Below are two approaches: a minimal apt-get install for Debian‑based images and a multi‑stage build that pulls a pre‑compiled static binary.
Approach A – apt‑get installation (Debian/Ubuntu based)
# Dockerfile – before
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "run.py"]
# Dockerfile – after
FROM python:3.10-slim
# Install ffmpeg and its shared libraries
RUN apt-get update && \
apt-get install -y --no-install-recommends ffmpeg && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "run.py"]
Approach B – static binary (alpine or distroless base)
# Dockerfile – before (alpine)
FROM python:3.10-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "run.py"]
# Dockerfile – after (alpine + static ffmpeg)
FROM python:3.10-alpine
# Download a static build of ffmpeg
ENV FFMPEG_VERSION=6.0
RUN wget -O /tmp/ffmpeg.tar.xz \
https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-${FFMPEG_VERSION}-amd64-static.tar.xz && \
tar -xJf /tmp/ffmpeg.tar.xz -C /opt && \
ln -s /opt/ffmpeg-${FFMPEG_VERSION}-amd64-static/ffmpeg /usr/local/bin/ffmpeg && \
ln -s /opt/ffmpeg-${FFMPEG_VERSION}-amd64-static/ffprobe /usr/local/bin/ffprobe && \
rm /tmp/ffmpeg.tar.xz
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "run.py"]
Both approaches place ffmpeg in /usr/local/bin, which is already part of the default PATH.
Verify
1. Rebuild and run the container
docker build -t mlflow-audio .
docker run -d --name mlflow-test -p 5000:5000 mlflow-audio
2. Confirm ffmpeg availability
docker exec -it mlflow-test ffmpeg -version
ffmpeg version 6.0-...
...
3. Execute a minimal logging script
# log_audio.py
import mlflow
import numpy as np
import soundfile as sf
import os
# Generate a 1‑second 440 Hz sine wave
sr = 22050
t = np.linspace(0, 1, sr, False)
tone = 0.5 * np.sin(2 * np.pi * 440 * t)
os.makedirs("tmp", exist_ok=True)
sf.write("tmp/sine.wav", tone, sr)
with mlflow.start_run():
mlflow.log_artifact("tmp/sine.wav", artifact_path="audio")
print("Artifact logged")
docker exec -it mlflow-test python log_audio.py
Artifact logged
4. Verify artifact presence via the MLflow UI or CLI
mlflow artifacts list -r
audio/sine.wav
Prevent
- Base‑image selection: Prefer images that already contain multimedia utilities (e.g.,
python:3.10-slim-bullseyewithffmpegadded) to avoid ad‑hoc installs. - Dockerfile linting: Enforce a rule that
ffmpegmust be present when themlflow.audiomodule is imported. CI can rundocker run … which ffmpegas a sanity check. - Health‑check: Add a container health‑check that runs
ffmpeg -versionand fails if the exit code is non‑zero. - Version pinning: Install a specific
ffmpegversion to guarantee consistent codec support across environments. - Documentation: Clearly state the runtime dependency in the project’s README and in the
requirements.txt(as a comment) so new developers know to include it in custom images.
Related Topic Hub: Model Serving Troubleshooting Hub
FAQ
- Why does
mlflow.audio.log_artifactwork locally but not in CI?
CI pipelines often use minimal base images that lackffmpeg. The helper callssubprocess.run(["ffmpeg", …]), which fails when the binary is missing. - Can I use a pure‑Python library instead of
ffmpeg?
MLflow delegates audio probing toffprobefor reliable codec detection. Replacing it would require modifying MLflow’s source; installing the binary is the supported path. - Is
ffmpegrequired for non‑audio artifacts?
No. Only themlflow.audiomodule triggers the dependency. Other artifact types (e.g., model files, CSVs) do not need it. - What if I need a specific codec that the default
ffmpegpackage lacks?
Install the fullffmpegpackage (not the-ffmpegminimal variant) or compile a custom static binary with the required codec enabled, then replace the binary in the image. - How do I debug a “ffprobe not found” error?
Rundocker exec. If missing, addwhich ffprobe ffprobeto the image (it ships with the same package asffmpegon Debian/Ubuntu). Verify that both binaries are onPATHand that the container’sLD_LIBRARY_PATHincludes any required shared libraries.