|
1 | | -# This sample Dockerfile creates a production-ready container for a LiveKit voice AI agent |
| 1 | +# This is an example Dockerfile that builds a minimal container for running LK Agents |
| 2 | +# For more information on the build process, see https://docs.livekit.io/agents/ops/deployment/builds/ |
2 | 3 | # syntax=docker/dockerfile:1 |
3 | 4 |
|
4 | 5 | # Use the official UV Python base image with Python 3.11 on Debian Bookworm |
5 | 6 | # UV is a fast Python package manager that provides better performance than pip |
6 | 7 | # We use the slim variant to keep the image size smaller while still having essential tools |
7 | | -FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim |
| 8 | +ARG PYTHON_VERSION=3.11 |
| 9 | +FROM ghcr.io/astral-sh/uv:python${PYTHON_VERSION}-bookworm-slim AS base |
8 | 10 |
|
9 | 11 | # Keeps Python from buffering stdout and stderr to avoid situations where |
10 | 12 | # the application crashes without emitting any logs due to buffering. |
11 | 13 | ENV PYTHONUNBUFFERED=1 |
12 | 14 |
|
13 | | -# Define the program entrypoint file where your agent is started. |
14 | | -ARG PROGRAM_MAIN="{{.ProgramMain}}" |
15 | | - |
16 | 15 | # Create a non-privileged user that the app will run under. |
17 | 16 | # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user |
18 | 17 | ARG UID=10001 |
19 | 18 | RUN adduser \ |
20 | 19 | --disabled-password \ |
21 | 20 | --gecos "" \ |
22 | | - --home "/home/appuser" \ |
| 21 | + --home "/app" \ |
23 | 22 | --shell "/sbin/nologin" \ |
24 | 23 | --uid "${UID}" \ |
25 | 24 | appuser |
26 | 25 |
|
27 | 26 | # Install build dependencies required for Python packages with native extensions |
28 | 27 | # gcc: C compiler needed for building Python packages with C extensions |
| 28 | +# g++: C++ compiler needed for building Python packages with C++ extensions |
29 | 29 | # python3-dev: Python development headers needed for compilation |
30 | 30 | # We clean up the apt cache after installation to keep the image size down |
31 | | -RUN apt-get update && \ |
32 | | - apt-get install -y \ |
| 31 | +RUN apt-get update && apt-get install -y \ |
33 | 32 | gcc \ |
| 33 | + g++ \ |
34 | 34 | python3-dev \ |
35 | | - && rm -rf /var/lib/apt/lists/* |
| 35 | + && rm -rf /var/lib/apt/lists/* |
| 36 | + |
| 37 | +# Create a new directory for our application code |
| 38 | +# And set it as the working directory |
| 39 | +WORKDIR /app |
36 | 40 |
|
37 | | -# Set the working directory to the user's home directory |
38 | | -# This is where our application code will live |
39 | | -WORKDIR /home/appuser |
| 41 | +# Copy just the dependency files first, for more efficient layer caching |
| 42 | +COPY pyproject.toml uv.lock ./ |
| 43 | +RUN mkdir -p src |
40 | 44 |
|
41 | | -# Copy all application files into the container |
| 45 | +# Install Python dependencies using UV's lock file |
| 46 | +# --locked ensures we use exact versions from uv.lock for reproducible builds |
| 47 | +# This creates a virtual environment and installs all dependencies |
| 48 | +# Ensure your uv.lock file is checked in for consistency across environments |
| 49 | +RUN uv sync --locked |
| 50 | + |
| 51 | +# Copy all remaining pplication files into the container |
42 | 52 | # This includes source code, configuration files, and dependency specifications |
43 | 53 | # (Excludes files specified in .dockerignore) |
44 | 54 | COPY . . |
45 | 55 |
|
46 | 56 | # Change ownership of all app files to the non-privileged user |
47 | 57 | # This ensures the application can read/write files as needed |
48 | | -RUN chown -R appuser:appuser /home/appuser |
| 58 | +RUN chown -R appuser:appuser /app |
49 | 59 |
|
50 | 60 | # Switch to the non-privileged user for all subsequent operations |
51 | 61 | # This improves security by not running as root |
52 | 62 | USER appuser |
53 | 63 |
|
54 | | -# Create a cache directory for the user |
55 | | -# This is used by UV and Python for caching packages and bytecode |
56 | | -RUN mkdir -p /home/appuser/.cache |
57 | | - |
58 | | -# Install Python dependencies using UV's lock file |
59 | | -# --locked ensures we use exact versions from uv.lock for reproducible builds |
60 | | -# This creates a virtual environment and installs all dependencies |
61 | | -# Ensure your uv.lock file is checked in for consistency across environments |
62 | | -RUN uv sync --locked |
63 | | - |
64 | 64 | # Pre-download any ML models or files the agent needs |
65 | 65 | # This ensures the container is ready to run immediately without downloading |
66 | 66 | # dependencies at runtime, which improves startup time and reliability |
67 | | -RUN uv run "$PROGRAM_MAIN" download-files |
68 | | - |
69 | | -# Expose the healthcheck port |
70 | | -# This allows Docker and orchestration systems to check if the container is healthy |
71 | | -EXPOSE 8081 |
| 67 | +RUN uv run "{{.ProgramMain}}" download-files |
72 | 68 |
|
73 | 69 | # Run the application using UV |
74 | 70 | # UV will activate the virtual environment and run the agent. |
75 | 71 | # The "start" command tells the worker to connect to LiveKit and begin waiting for jobs. |
76 | 72 | CMD ["uv", "run", "{{.ProgramMain}}", "start"] |
77 | | - |
0 commit comments