22# For more information on the build process, see https://docs.livekit.io/agents/ops/deployment/builds/
33# syntax=docker/dockerfile:1
44
5- # Use the official Node.js v22 base image with Node.js 22.10.0
5+ # Use the official Node.js v22 base image
66# We use the slim variant to keep the image size smaller while still having essential tools
77ARG NODE_VERSION=22
88FROM node:${NODE_VERSION}-slim AS base
@@ -19,6 +19,10 @@ RUN apt-get update -qq && apt-get install --no-install-recommends -y ca-certific
1919# Pin pnpm version for reproducible builds
2020RUN npm install -g pnpm@10
2121
22+ # --- Build stage ---
23+ # Install dependencies, build the project, and prepare production assets
24+ FROM base AS build
25+
2226# Create a new directory for our application code
2327# And set it as the working directory
2428WORKDIR /app
@@ -30,7 +34,7 @@ COPY package.json pnpm-lock.yaml ./
3034# --frozen-lockfile ensures we use exact versions from pnpm-lock.yaml for reproducible builds
3135RUN pnpm install --frozen-lockfile
3236
33- # Copy all remaining pplication files into the container
37+ # Copy all remaining application files into the container
3438# This includes source code, configuration files, and dependency specifications
3539# (Excludes files specified in .dockerignore)
3640COPY . .
@@ -39,8 +43,20 @@ COPY . .
3943# Your package.json must contain a "build" script, such as `"build": "tsc"`
4044RUN pnpm build
4145
46+ # Pre-download any ML models or files the agent needs
47+ # This ensures the container is ready to run immediately without downloading
48+ # dependencies at runtime, which improves startup time and reliability
49+ # Your package.json must contain a "download-files" script, such as `"download-files": "pnpm run build && node dist/agent.js download-files"`
50+ RUN pnpm download-files
51+
52+ # Remove dev dependencies for a leaner production image
53+ RUN pnpm prune --prod
54+
55+ # --- Production stage ---
56+ FROM base
57+
4258# Create a non-privileged user that the app will run under
43- # See https://docs.docker.com/develop/develop-images/dockerfile_best_practices /#user
59+ # See https://docs.docker.com/build/building/best-practices /#user
4460ARG UID=10001
4561RUN adduser \
4662 --disabled-password \
@@ -50,19 +66,12 @@ RUN adduser \
5066 --uid "${UID}" \
5167 appuser
5268
53- # Set proper permissions
54- RUN chown -R appuser:appuser /app
55- USER appuser
69+ WORKDIR /app
5670
57- # Pre-download any ML models or files the agent needs
58- # This ensures the container is ready to run immediately without downloading
59- # dependencies at runtime, which improves startup time and reliability
60- # Your package.json must contain a "download-files" script, such as `"download-files": "pnpm run build && node dist/agent.js download-files"`
61- RUN pnpm download-files
71+ # Copy the built application with correct ownership in a single layer
72+ # This avoids expensive recursive chown operations on node_modules
73+ COPY --from=build --chown=appuser:appuser /app /app
6274
63- # Switch back to root to remove dev dependencies and finalize setup
64- USER root
65- RUN pnpm prune --prod && chown -R appuser:appuser /app
6675USER appuser
6776
6877# Set Node.js to production mode
@@ -71,4 +80,4 @@ ENV NODE_ENV=production
7180# Run the application
7281# The "start" command tells the worker to connect to LiveKit and begin waiting for jobs.
7382# Your package.json must contain a "start" script, such as `"start": "node dist/agent.js start"`
74- CMD [ "pnpm" , "start" ]
83+ CMD [ "pnpm" , "start" ]
0 commit comments