Docker Deployment#
Deploy embapi using Docker containers. This is the recommended approach for most users.
Quick Start#
The fastest way to get embapi running with Docker:
# Clone the repository
git clone https://github.com/mpilhlt/embapi.git
cd embapi
# Run automated setup (generates secure keys)
./docker-setup.sh
# Start services with docker-compose
docker-compose up -d
# Check logs
docker-compose logs -f embapi
# Access the API
curl http://localhost:8880/docsWhat’s Included#
The Docker Compose setup includes:
- embapi: The vector database API service
- PostgreSQL 16: Database with pgvector extension
- Persistent storage: Named volume for database data
Configuration Files#
.env File#
All configuration is managed through environment variables. Copy the template:
cp .env.docker.template .envEdit .env to set required values:
# Admin API key for administrative operations
SERVICE_ADMINKEY=your-secure-admin-key-here
# Encryption key for API keys (32+ characters)
ENCRYPTION_KEY=your-secure-encryption-key-min-32-chars
# Database password
SERVICE_DBPASSWORD=secure-database-password
# Optional: Debug mode
SERVICE_DEBUG=false
# Optional: Change ports
API_PORT=8880
POSTGRES_PORT=5432docker-compose.yml#
The compose file defines two services:
services:
postgres:
image: pgvector/pgvector:0.7.4-pg16
# PostgreSQL with pgvector support
embapi:
build: .
# The API service
depends_on:
- postgresDeployment Options#
Option 1: Docker Compose with Included Database (Recommended)#
Use the provided docker-compose.yml:
docker-compose up -dAdvantages:
- Everything included
- Automatic networking
- Data persistence
- Easy to manage
Use when:
- Getting started
- Development/testing
- Small to medium deployments
Option 2: Standalone Container with External Database#
Run only the embapi container:
# Build the image
docker build -t embapi:latest .
# Run the container
docker run -d \
--name embapi \
-p 8880:8880 \
-e SERVICE_DBHOST=your-db-host \
-e SERVICE_DBPORT=5432 \
-e SERVICE_DBUSER=dbuser \
-e SERVICE_DBPASSWORD=dbpass \
-e SERVICE_DBNAME=embapi \
-e SERVICE_ADMINKEY=admin-key \
-e ENCRYPTION_KEY=encryption-key \
embapi:latestUse when:
- You have an existing PostgreSQL server
- Production deployments
- Need database separation
Option 3: Docker Compose with External Database#
Modify docker-compose.yml to remove the postgres service:
services:
embapi:
build: .
ports:
- "${API_PORT:-8880}:8880"
environment:
SERVICE_DBHOST: external-db.example.com
# ... other variablesBuilding the Image#
Standard Build#
docker build -t embapi:latest .Custom Tag#
docker build -t embapi:v0.1.0 .Clean Build (No Cache)#
docker build --no-cache -t embapi:latest .Multi-Stage Build Details#
The Dockerfile uses multi-stage builds for efficiency:
- Builder stage: Compiles Go code with sqlc generation
- Runtime stage: Minimal Alpine image with only the binary
Result: Small, secure image (~20MB vs 800MB+)
Managing Services#
Start Services#
# Start in background
docker-compose up -d
# Start with logs visible
docker-compose up
# Rebuild and start
docker-compose up -d --buildView Logs#
# All logs
docker-compose logs
# Follow logs in real-time
docker-compose logs -f
# Specific service
docker-compose logs -f embapi
docker-compose logs -f postgresStop Services#
# Stop containers (keeps data)
docker-compose stop
# Stop and remove containers (keeps data)
docker-compose down
# Stop and remove everything including data
docker-compose down -vRestart Services#
# Restart all
docker-compose restart
# Restart specific service
docker-compose restart embapiData Persistence#
Docker Volumes#
The compose file creates a named volume:
volumes:
postgres_data:This ensures database data persists across container restarts.
View Volumes#
docker volume lsInspect Volume#
docker volume inspect embapi_postgres_dataBackup Database#
# Create backup
docker-compose exec postgres pg_dump -U postgres embapi > backup.sql
# Restore from backup
docker-compose exec -T postgres psql -U postgres embapi < backup.sqlNetworking#
Access from Host#
The API is accessible at:
http://localhost:8880Access from Other Containers#
Use the service name as hostname:
http://embapi:8880Custom Network#
To use an existing Docker network:
networks:
default:
external:
name: your-network-nameSecurity#
Required Environment Variables#
Two critical environment variables must be set:
- SERVICE_ADMINKEY: Admin API key
- ENCRYPTION_KEY: For encrypting user API keys (32+ chars)
Generating Secure Keys#
# Admin key
openssl rand -base64 32
# Encryption key
openssl rand -hex 32Production Checklist#
- Use strong, randomly generated keys
- Never commit
.envto version control - Run behind reverse proxy (nginx, Traefik)
- Enable HTTPS/TLS
- Restrict database network access
- Set resource limits
- Enable logging and monitoring
- Use specific image tags (not
latest) - Regular security updates
- Backup database regularly
Verification#
Check Service Status#
# Check if containers are running
docker-compose ps
# Expected: both services "running" or "healthy"Test API Access#
# Get OpenAPI documentation
curl http://localhost:8880/docs
# Should return HTML pageTest Database Connection#
# Connect to PostgreSQL
docker-compose exec postgres psql -U postgres -d embapi
# Check pgvector extension
\dx
# Should show vector extensionCreate Test User#
curl -X POST http://localhost:8880/v1/users \
-H "Authorization: Bearer YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_handle": "testuser",
"full_name": "Test User"
}'Troubleshooting#
Container Won’t Start#
Check logs:
docker-compose logs embapiCommon issues:
- Missing
SERVICE_ADMINKEYorENCRYPTION_KEY - Database connection failure
- Port already in use
Database Connection Errors#
# Check postgres health
docker-compose ps
# Check database logs
docker-compose logs postgres
# Test connection
docker-compose exec postgres psql -U postgres -d embapi -c "SELECT 1;"Can’t Connect to API#
# Check if container is running
docker ps
# Check port mapping
docker port embapi
# Test from inside container
docker-compose exec embapi wget -O- http://localhost:8880/docs
# Test from host
curl http://localhost:8880/docsPermission Issues#
The container runs as non-root user appuser (UID 1000). If you have permission errors:
# Check volume permissions
docker volume inspect embapi_postgres_dataReset Everything#
# Stop and remove everything
docker-compose down -v
# Remove images
docker rmi embapi:latest
docker rmi pgvector/pgvector:0.7.4-pg16
# Start fresh
docker-compose up -d --buildBuild Failures#
If Docker build fails with network errors:
# Try with host network
docker build --network=host -t embapi:latest .Advanced Configuration#
Resource Limits#
Add to docker-compose.yml:
services:
embapi:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512MHealth Checks#
The Dockerfile includes a health check:
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:8880/ || exit 1View health status:
docker inspect --format='{{.State.Health.Status}}' embapiCustom Dockerfile Builds#
You can customize the build:
docker build \
--build-arg GO_VERSION=1.24 \
-t embapi:custom .External Database Setup#
If using an external PostgreSQL database:
Prepare Database#
-- Create database
CREATE DATABASE embapi;
-- Create user
CREATE USER embapi_user WITH PASSWORD 'secure_password';
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE embapi TO embapi_user;
-- Connect to database
\c embapi
-- Grant schema permissions
GRANT ALL ON SCHEMA public TO embapi_user;
-- Enable pgvector
CREATE EXTENSION IF NOT EXISTS vector;Configure embapi#
Update .env:
SERVICE_DBHOST=external-db.example.com
SERVICE_DBPORT=5432
SERVICE_DBUSER=embapi_user
SERVICE_DBPASSWORD=secure_password
SERVICE_DBNAME=embapiThen run only the embapi service or use a standalone container.
Next Steps#
After successful deployment: