Skip to main content

Builds and Dockerfiles

Guide to the LiveKit Cloud build process, plus Dockerfile templates and resources.

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:

  1. 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.
  2. Exclusions: The build context excludes .env.* files and any files matched by .dockerignore or .gitignore.
  3. Upload: The CLI uploads the prepared build context to the LiveKit Cloud build service.
  4. 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.
  • 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, or LIVEKIT_API_SECRET environment variables. These are injected at runtime by LiveKit Cloud.
  • Startup command: Provide a fixed ENTRYPOINT/CMD that directly launches the agent using the start 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 tools
ARG PYTHON_VERSION=3.11
FROM 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/#user
ARG UID=10001
RUN 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 down
RUN 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 directory
WORKDIR /app
# Copy just the dependency files first, for more efficient layer caching
COPY 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 environments
RUN 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 needed
RUN chown -R appuser:appuser /app
# Switch to the non-privileged user for all subsequent operations
# This improves security by not running as root
USER 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 reliability
RUN 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"]