Docker Deployment
This guide explains how to deploy pgEdge RAG Server using Docker and Docker Compose.
Prerequisites
Before deploying with Docker, ensure you have:
- Docker Engine 20.10 or later
- Docker Compose V2 or later
- API keys for your chosen LLM providers (see Managing API Keys)
Quick Start
1. Clone the Repository
git clone https://github.com/pgedge/pgedge-rag-server.git
cd pgedge-rag-server
2. Configure Environment Variables
Copy the example environment file and configure your API keys:
cp docker.env.example .env
Edit the .env file and add your API keys:
# Required: Add your API keys
OPENAI_API_KEY=sk-your-openai-key-here
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key-here
# Optional: Customize ports and credentials
POSTGRES_PASSWORD=your-secure-password
RAG_SERVER_PORT=8080
3. Configure the RAG Server
The repository includes a sample configuration file
pgedge-rag-server.yaml. Review and customize it for your needs:
- Update database credentials if you changed them in
.env - Configure your pipelines with appropriate tables and columns
- Select your preferred embedding and LLM models
See Creating a Configuration File for detailed configuration options.
4. Start the Services
docker compose up -d
This command will:
- Pull the PostgreSQL with pgvector image
- Build the RAG server Docker image
- Start both services
- Initialize the database with pgvector extension and sample schema
5. Verify the Deployment
Check that the services are running:
docker compose ps
Test the RAG server:
curl http://localhost:8080/v1/pipelines
Using Pre-built Images
Instead of building locally, you can use pre-built images from GitHub Container Registry:
docker pull ghcr.io/pgedge/rag-server:latest
Update your docker-compose.yml to use the pre-built image:
services:
rag-server:
image: ghcr.io/pgedge/rag-server:latest
# Remove the 'build' section
Database Initialization
The included init-db.sql script automatically:
- Enables the pgvector extension
- Creates a sample
documentstable with vector columns - Creates indexes for vector similarity search
- Creates indexes for BM25 text search (hybrid mode)
Customizing the Schema
To customize the database schema:
- Edit
init-db.sqlto match your data structure - Adjust vector dimensions based on your embedding model:
- OpenAI text-embedding-3-small: 1536 dimensions
- OpenAI text-embedding-3-large: 3072 dimensions
- Voyage AI models: 1024 or 1536 dimensions
- Update
pgedge-rag-server.yamlto reference your table and column names - Restart the services:
docker compose down && docker compose up -d
Populating Your Database
After starting the services, populate your database with content:
# Connect to the PostgreSQL container
docker compose exec postgres psql -U postgres -d ragdb
# Insert sample documents (adjust vector dimensions as needed)
INSERT INTO documents (content, title, source) VALUES
('Your document content here', 'Document Title', 'source-name');
For production use, you'll typically:
- Generate embeddings using your embedding model
- Insert both the text content and embeddings into the database
- Ensure the vector dimensions match your embedding model
Managing the Deployment
View Logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f rag-server
docker compose logs -f postgres
Stop Services
docker compose stop
Restart Services
docker compose restart
Remove Services and Data
# Stop and remove containers (preserves data volumes)
docker compose down
# Remove everything including data volumes
docker compose down -v
Update the RAG Server
To update to a new version:
# Pull the latest image
docker compose pull rag-server
# Restart the service
docker compose up -d rag-server
Production Considerations
For production deployments, consider:
Security
- Never commit
.envfiles to version control - Use strong passwords for PostgreSQL
- Enable TLS/HTTPS for the RAG server (see Configuration)
- Put an authenticating proxy in front of the server; see the warning below
- Restrict network access using Docker network policies
- Use secrets management (Docker Secrets, Kubernetes Secrets, etc.)
TLS is not access control
The RAG server implements neither client authentication nor rate limiting, so every endpoint it exposes is reachable by anyone who can reach the port, and any such caller can issue as many queries as they like. Enabling TLS encrypts the connection and authenticates the server to the client, but it does nothing to establish who the client is, and it places no bound on how often they may call; a TLS-only deployment is still an open one. A production setup therefore needs an authenticating reverse proxy or API gateway (nginx, Caddy, Envoy, or similar) in front of the service, handling both authentication and rate limiting, with the RAG server itself bound to a private network rather than published directly. See Authentication and Rate Limiting in the API reference.
Data Persistence
The docker-compose setup uses Docker volumes for PostgreSQL data:
volumes:
postgres_data:
driver: local
For production:
- Use named volumes or bind mounts to specific host paths
- Implement regular backup strategies
- Consider using managed PostgreSQL services
Resource Limits
Add resource constraints to your docker-compose.yml:
services:
rag-server:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
High Availability
For high availability:
- Deploy multiple RAG server instances behind a load balancer
- Use PostgreSQL replication for database redundancy
- Consider orchestration platforms like Kubernetes
Troubleshooting
Service Won't Start
Check logs for errors:
docker compose logs rag-server
Common issues:
- Missing or invalid API keys in
.env - Configuration file syntax errors
- Port conflicts (8080 or 5432 already in use)
Cannot Connect to PostgreSQL
Verify the database is ready:
docker compose exec postgres pg_isready -U postgres
If the database isn't ready, wait a few moments for initialization to complete.
pgvector Extension Not Found
Ensure you're using the pgvector/pgvector Docker image, which
includes the extension pre-installed.
Configuration Changes Not Applied
The server normally picks up configuration changes on its own, without a
restart, as described under
Configuration Reloading.
The docker-compose.yml shipped here is the exception, because it
bind-mounts the configuration as a single file:
volumes:
- ./pgedge-rag-server.yaml:/etc/pgedge/pgedge-rag-server.yaml:ro
Change detection works by watching the directory that contains the
watched file rather than the file itself, and with a single-file bind
mount, the directory the container sees (/etc/pgedge) is not the host
directory you edited in, so an edit on the host generates no event
inside the container and no reload follows. Editors that save by writing
a temporary file and renaming it over the original are worse still: the
rename replaces the host inode, which detaches the bind mount
altogether, leaving the container reading the original file
indefinitely.
So under Docker, after modifying pgedge-rag-server.yaml, restart the
service:
docker compose restart rag-server
The mount being read-only does not get in the way of this; it only stops the server writing to the file.
If you would rather have automatic reloads in a container, mount the containing directory instead of the individual file, so that the container and the host share the directory the watcher is watching:
volumes:
- ./config:/etc/pgedge:ro
with pgedge-rag-server.yaml inside ./config. This is also how a
Kubernetes ConfigMap volume behaves, which is why reloads work there
without any of this ceremony. Note that changes to server-level
settings (listen_address, port, tls, and cors) are read only at
startup and always need a restart, however the file is mounted.