Docker Deployment
This guide provides detailed information about running llms.py in Docker.
Quick Start
Section titled “Quick Start”Using Pre-built Images
Section titled “Using Pre-built Images”# Pull and run the latest imagedocker pull ghcr.io/servicestack/llms:latestdocker run -p 8000:8000 -e OPENROUTER_API_KEY="your-key" ghcr.io/servicestack/llms:latestUsing docker compose (Recommended)
Section titled “Using docker compose (Recommended)”- Create a
.envfile with your API keys:
OPENROUTER_API_KEY=sk-or-...GROQ_API_KEY=gsk_...GOOGLE_FREE_API_KEY=AIza...ANTHROPIC_API_KEY=sk-ant-...OPENAI_API_KEY=sk-...GROK_API_KEY=xai-...DASHSCOPE_API_KEY=sk-...ZAI_API_KEY=sk-...MISTRAL_API_KEY=...- Start the service:
docker compose up -d- Access the UI at http://localhost:8000
Files Created
Section titled “Files Created”Dockerfile
Section titled “Dockerfile”Multi-stage Docker build that:
- Uses Python 3.11 slim base image
- Builds the package from source
- Runs as non-root user for security
- Includes health checks
- Exposes port 8000
- Default command:
llms --serve 8000
.dockerignore
Section titled “.dockerignore”Excludes unnecessary files from the Docker build context to reduce image size and build time.
docker compose.yml
Section titled “docker compose.yml”Provides easy orchestration with:
- Port mapping (8000:8000)
- Environment variable support via .env file
- Named volume for data persistence
- Automatic restart policy
- Health checks
docker-build.sh
Section titled “docker-build.sh”Convenience script for building the Docker image locally:
./docker-build.sh [tag].github/workflows/docker-publish.yml
Section titled “.github/workflows/docker-publish.yml”GitHub Actions workflow that:
- Builds Docker images on push to main and tags
- Publishes to GitHub Container Registry (ghcr.io)
- Supports multi-architecture builds (amd64, arm64)
- Creates image tags for branches, PRs, and semantic versions
- Uses Docker layer caching for faster builds
Usage Examples
Section titled “Usage Examples”Basic Server
Section titled “Basic Server”docker run -p 8000:8000 \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestWith Multiple API Keys
Section titled “With Multiple API Keys”docker run -p 8000:8000 \ -e OPENROUTER_API_KEY="sk-or-..." \ -e GROQ_API_KEY="gsk_..." \ -e GOOGLE_FREE_API_KEY="AIza..." \ -e ANTHROPIC_API_KEY="sk-ant-..." \ ghcr.io/servicestack/llms:latestWith Persistent Storage
Section titled “With Persistent Storage”docker run -p 8000:8000 \ -v llms-data:/home/llms/.llms \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestCLI Usage
Section titled “CLI Usage”# Single querydocker run --rm \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latest \ llms "What is the capital of France?"
# List modelsdocker run --rm \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latest \ llms --list
# Check providerdocker run --rm \ -e GROQ_API_KEY="your-key" \ ghcr.io/servicestack/llms:latest \ llms --check groqCustom Port
Section titled “Custom Port”# Run on port 3000docker run -p 3000:8000 \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestWith Verbose Logging
Section titled “With Verbose Logging”docker run -p 8000:8000 \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latest \ llms --serve 8000 --verboseBuilding Locally
Section titled “Building Locally”Using the Build Script
Section titled “Using the Build Script”./docker-build.shThis builds the image as llms-py:latest.
Manual Build
Section titled “Manual Build”docker build -t llms-py:latest .Build with Custom Tag
Section titled “Build with Custom Tag”./docker-build.sh v2.0.24Docker Compose
Section titled “Docker Compose”Using Pre-built Image (Recommended for Users)
Section titled “Using Pre-built Image (Recommended for Users)”The default docker compose.yml uses the pre-built image from GitHub Container Registry:
# Start servicesdocker compose up -d
# View logsdocker compose logs -f
# Stop servicesdocker compose downBuilding from Source (For Developers)
Section titled “Building from Source (For Developers)”If you’ve cloned the repository and want to build from source, use docker compose.local.yml:
# Build and start servicesdocker compose -f docker compose.local.yml up -d --build
# View logsdocker compose -f docker compose.local.yml logs -f
# Stop servicesdocker compose -f docker compose.local.yml down
# Rebuild and restartdocker compose -f docker compose.local.yml up -d --buildData Persistence
Section titled “Data Persistence”The container stores configuration and analytics data in /home/llms/.llms.
On first run, the container will automatically create default llms.json and ui.json files in this directory.
Named Volume (Recommended)
Section titled “Named Volume (Recommended)”docker run -p 8000:8000 \ -v llms-data:/home/llms/.llms \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestLocal Directory
Section titled “Local Directory”docker run -p 8000:8000 \ -v $(pwd)/llms-config:/home/llms/.llms \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestCustom Configuration Files
Section titled “Custom Configuration Files”You can customize the behavior of llms-py by providing your own llms.json and ui.json configuration files.
Method 1: Mount a Local Directory (Recommended)
Section titled “Method 1: Mount a Local Directory (Recommended)”- Create a local directory with your custom config files:
# Option A: Use the provided extraction script (easiest)./docker-extract-configs.sh config
# Option B: Manual extractionmkdir -p configdocker run --rm -v $(pwd)/config:/home/llms/.llms \ ghcr.io/servicestack/llms:latest \ llms --init-
Edit
config/llms.jsonandconfig/ui.jsonto your preferences -
Mount the directory when running the container:
docker run -p 8000:8000 \ -v $(pwd)/config:/home/llms/.llms \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestOr with docker compose, update the volumes section:
volumes: - ./config:/home/llms/.llmsMethod 2: Mount Individual Config Files
Section titled “Method 2: Mount Individual Config Files”Mount specific config files (read-only recommended to prevent accidental changes):
docker run -p 8000:8000 \ -v $(pwd)/my-llms.json:/home/llms/.llms/llms.json:ro \ -v $(pwd)/my-ui.json:/home/llms/.llms/ui.json:ro \ -e OPENROUTER_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestOr with docker compose:
volumes: - ./my-llms.json:/home/llms/.llms/llms.json:ro - ./my-ui.json:/home/llms/.llms/ui.json:roMethod 3: Initialize and Extract Configs
Section titled “Method 3: Initialize and Extract Configs”- Run the container with a named volume to initialize default configs:
docker run --rm \ -v llms-data:/home/llms/.llms \ ghcr.io/servicestack/llms:latest \ llms --init- Extract the configs to customize them:
# Create a temporary container to copy filesdocker run -d --name llms-temp -v llms-data:/home/llms/.llms ghcr.io/servicestack/llms:latest sleep 60docker cp llms-temp:/home/llms/.llms/llms.json ./llms.jsondocker cp llms-temp:/home/llms/.llms/ui.json ./ui.jsondocker rm -f llms-temp- Edit the files and copy them back:
# After editing, copy backdocker run -d --name llms-temp -v llms-data:/home/llms/.llms ghcr.io/servicestack/llms:latest sleep 60docker cp ./llms.json llms-temp:/home/llms/.llms/llms.jsondocker cp ./ui.json llms-temp:/home/llms/.llms/ui.jsondocker rm -f llms-tempWhat Can You Customize?
Section titled “What Can You Customize?”In llms.json:
- Enable/disable providers
- Add or remove models
- Configure API endpoints
- Set pricing information
- Customize default chat templates
- Configure provider-specific settings
In ui.json:
- UI theme and appearance
- Default model selections
- UI feature toggles
- Custom UI configurations
Example: Custom Provider Configuration
Section titled “Example: Custom Provider Configuration”Create a custom llms.json with only the providers you want:
{ "defaults": { "headers": { "Content-Type": "application/json" }, "text": { "model": "llama3.3:70b", "messages": [ { "role": "user", "content": "" } ] } }, "providers": { "groq": { "enabled": true, "type": "OpenAiProvider", "base_url": "https://api.groq.com/openai", "api_key": "$GROQ_API_KEY", "models": { "llama3.3:70b": "llama-3.3-70b-versatile" } } }}Then mount it:
docker run -p 8000:8000 \ -v $(pwd)/custom-llms.json:/home/llms/.llms/llms.json:ro \ -e GROQ_API_KEY="your-key" \ ghcr.io/servicestack/llms:latestHealth Checks
Section titled “Health Checks”The Docker image includes a health check that verifies the server is responding.
Check Container Health
Section titled “Check Container Health”docker psLook for the health status in the STATUS column.
View Health Check Details
Section titled “View Health Check Details”docker inspect --format='{{json .State.Health}}' llms-server | jqMulti-Architecture Support
Section titled “Multi-Architecture Support”The published Docker images support:
linux/amd64(Intel/AMD x86_64)linux/arm64(ARM64/Apple Silicon)
Docker automatically pulls the correct image for your platform.
GitHub Container Registry
Section titled “GitHub Container Registry”Images are automatically published to GitHub Container Registry on:
- Push to main branch →
ghcr.io/servicestack/llms:main - Tagged releases →
ghcr.io/servicestack/llms:v2.0.24 - Latest tag →
ghcr.io/servicestack/llms:latest
Pull Specific Version
Section titled “Pull Specific Version”docker pull ghcr.io/servicestack/llms:v2.0.24Pull Latest
Section titled “Pull Latest”docker pull ghcr.io/servicestack/llms:latestTroubleshooting
Section titled “Troubleshooting”Container Won’t Start
Section titled “Container Won’t Start”Check logs:
docker logs llms-serverPermission Issues
Section titled “Permission Issues”The container runs as user llms (UID 1000). If mounting local directories, ensure they’re writable:
mkdir -p llms-configchmod 777 llms-configPort Already in Use
Section titled “Port Already in Use”Change the host port:
docker run -p 3000:8000 ...API Keys Not Working
Section titled “API Keys Not Working”Verify environment variables are set:
docker exec llms-server env | grep API_KEYSecurity Considerations
Section titled “Security Considerations”- Container runs as non-root user (UID 1000)
- Only port 8000 is exposed
- No unnecessary packages installed
- Multi-stage build reduces attack surface
- Health checks ensure service availability
Performance
Section titled “Performance”- Multi-stage build keeps final image small
- Layer caching speeds up rebuilds
- aiohttp provides async performance
- Health checks prevent routing to unhealthy containers
Next Steps
Section titled “Next Steps”- Server Mode - API server details
- Configuration - Customize settings
- API Keys - Set up providers