Build process
LiveKit Cloud builds container images for your agents based on your code and Dockerfile, when you run lk agent create
or lk agent deploy
. This build occurs on the LiveKit Cloud build service. The process is as follows:
- Gather files: The CLI prepares a build context from your working directory, which is the directory you run the command from. To use a different directory, pass it explicitly, for example
lk agent deploy /path/to/code
. - Exclusions: The build context excludes
.env.*
files and any files matched by.dockerignore
or.gitignore
. - Upload: The CLI uploads the prepared build context to the LiveKit Cloud build service.
- Build: The build service uses your Dockerfile to create the container image, streaming logs to the CLI.
After the build is complete, deployment begins. See Deploying new versions for more information.
To view build logs, see Build logs.
Build timeout
Builds have a maximum duration of 10 minutes. Builds exceeding this limit are terminated and the deployment fails.
Dockerfile
Most projects can use the default Dockerfile generated by the LiveKit CLI, which is based on the templates at the end of this section.
To create your own Dockerfile or modify the templates, refer to the following requirements and best practices:
- Base image: Use a glibc-based image such as Debian or Ubuntu. Alpine (musl) is not supported.
- LiveKit recommends using
-slim
images, which contain only the essential system packages for your runtime.
- LiveKit recommends using
- Unprivileged user: Do not run as the root user.
- Working directory: Set an explicit
WORKDIR
(for example,/app
). - Dependencies and caching:
- Copy lockfiles and manifests first, install dependencies, then copy the rest of the source to maximize cache reuse.
- Pin versions and use lockfiles.
- System packages and layers:
- Install required build tools up front.
- Clean package lists (for example,
/var/lib/apt/lists
) to keep layers small.
- Build time limit: Keep total build duration under 10 minutes; long builds fail due to the build timeout.
- Secrets and configuration:
- Do not copy
.env*
files or include secrets in the image. - Use LiveKit Cloud secrets management to inject any necessary secrets at runtime.
- Do not set
LIVEKIT_URL
,LIVEKIT_API_KEY
, orLIVEKIT_API_SECRET
environment variables. These are injected at runtime by LiveKit Cloud.
- Do not copy
- Startup command: Provide a fixed
ENTRYPOINT
/CMD
that directly launches the agent using thestart
command, without backgrounding or wrapper scripts. - Assets and models: Download models and other assets during the image build, not on first run, so containers start quickly. Use
download-files
to download assets required by LiveKit plugins.
Tips for Python projects
- Use the uv package manager: This modern Rust-based package manager is faster than pip, and supports lockfiles.
- The recommended base image for uv-based projects is
ghcr.io/astral-sh/uv:python3.11-bookworm-slim
(or another Python version). - The recommended base image for pip-based projects is
python:3.11-slim
(or another Python version). - Check your
uv.lock
file into source control. This ensures everyone on your team is using the same dependencies. - Install dependencies with
uv sync --locked
. This ensures that the dependencies in production always match
Tips for Node.js projects
- Use the pnpm package manager: This modern package manager is faster and more efficient than npm, and it's the recommended way to manage Node.js dependencies.
- The recommended base image for pnpm-based projects is
node:22-slim
(or another Node.js version).
Templates
These templates are automatically created by the LiveKit CLI to match your project type. They support both Python and Node.js projects.
The most up-to-date version of these templates is always available in the LiveKit CLI examples folder.
This template is offered for both uv and pip.
It assumes that your code in the src/
directory and your agent entrypoint is in src/agent.py
. You can modify these paths as needed.
# syntax=docker/dockerfile:1# Use the official UV Python base image with Python 3.11 on Debian Bookworm# UV is a fast Python package manager that provides better performance than pip# We use the slim variant to keep the image size smaller while still having essential toolsARG PYTHON_VERSION=3.11FROM ghcr.io/astral-sh/uv:python${PYTHON_VERSION}-bookworm-slim AS base# Keeps Python from buffering stdout and stderr to avoid situations where# the application crashes without emitting any logs due to buffering.ENV PYTHONUNBUFFERED=1# Create a non-privileged user that the app will run under.# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#userARG UID=10001RUN adduser \--disabled-password \--gecos "" \--home "/app" \--shell "/sbin/nologin" \--uid "${UID}" \appuser# Install build dependencies required for Python packages with native extensions# gcc: C compiler needed for building Python packages with C extensions# python3-dev: Python development headers needed for compilation# We clean up the apt cache after installation to keep the image size downRUN apt-get update && apt-get install -y \gcc \python3-dev \&& rm -rf /var/lib/apt/lists/*# Create a new directory for our application code# And set it as the working directoryWORKDIR /app# Copy just the dependency files first, for more efficient layer cachingCOPY pyproject.toml uv.lock ./RUN mkdir -p src# Install Python dependencies using UV's lock file# --locked ensures we use exact versions from uv.lock for reproducible builds# This creates a virtual environment and installs all dependencies# Ensure your uv.lock file is checked in for consistency across environmentsRUN uv sync --locked# Copy all remaining pplication files into the container# This includes source code, configuration files, and dependency specifications# (Excludes files specified in .dockerignore)COPY . .# Change ownership of all app files to the non-privileged user# This ensures the application can read/write files as neededRUN chown -R appuser:appuser /app# Switch to the non-privileged user for all subsequent operations# This improves security by not running as rootUSER appuser# Pre-download any ML models or files the agent needs# This ensures the container is ready to run immediately without downloading# dependencies at runtime, which improves startup time and reliabilityRUN uv run src/agent.py download-files# Run the application using UV# UV will activate the virtual environment and run the agent.# The "start" command tells the worker to connect to LiveKit and begin waiting for jobs.CMD ["uv", "run", "src/agent.py", "start"]