brainy/examples/docker-deployment/README.md

235 lines
5.6 KiB
Markdown
Raw Normal View History

# Docker Deployment for Brainy
This guide shows how to deploy Brainy applications with embedded models in Docker containers, avoiding the need to download models at runtime.
## Problem
When deploying Node.js applications to Docker containers, `node_modules` is often ignored in `.dockerignore` to reduce image size. However, this means the `@soulcraft/brainy-models` package (containing pre-trained models) won't be included in the container, forcing runtime model downloads from the internet.
## Solution
Brainy now supports loading models from custom directories using:
1. **Environment variable**: `BRAINY_MODELS_PATH` or `MODELS_PATH`
2. **Configuration option**: `customModelsPath` in `RobustModelLoader`
## Deployment Strategies
### Strategy 1: Embed Models in Docker Image (Recommended)
This approach copies models from `node_modules` to a custom location during the Docker build process.
```dockerfile
# Multi-stage build to extract models
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Extract models from node_modules
RUN mkdir -p /app/models && \
if [ -d "./node_modules/@soulcraft/brainy-models" ]; then \
cp -r ./node_modules/@soulcraft/brainy-models/models/* /app/models/; \
fi
# Production stage
FROM node:24-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production --omit=optional
COPY . .
COPY --from=builder /app/models /app/models
# Set environment variable
ENV BRAINY_MODELS_PATH=/app/models
CMD ["node", "dist/your-app.js"]
```
### Strategy 2: Mount Models as Volume
Mount pre-downloaded models as a Docker volume:
```yaml
services:
brainy-app:
image: your-brainy-app
environment:
- BRAINY_MODELS_PATH=/models
volumes:
- ./models:/models:ro
```
### Strategy 3: Init Container Pattern
Use an init container to download models before starting your application:
```yaml
services:
model-downloader:
image: node:24-alpine
volumes:
- brainy-models:/models
command: |
sh -c "
npm install @soulcraft/brainy-models
cp -r node_modules/@soulcraft/brainy-models/models/* /models/
"
brainy-app:
image: your-brainy-app
environment:
- BRAINY_MODELS_PATH=/models
volumes:
- brainy-models:/models:ro
depends_on:
- model-downloader
volumes:
brainy-models:
```
## Configuration Options
### Environment Variables
```bash
# Primary environment variable
BRAINY_MODELS_PATH=/app/models
# Alternative variable name
MODELS_PATH=/app/models
```
### Programmatic Configuration
```javascript
import { BrainyData, RobustModelLoader } from '@soulcraft/brainy'
// Option 1: Configure via RobustModelLoader
const loader = new RobustModelLoader({
customModelsPath: '/app/models'
})
// Option 2: Environment variable (automatic)
// Just set BRAINY_MODELS_PATH and it will be used automatically
```
## Model Directory Structure
Brainy will search for models in the following subdirectories (in order):
```
/app/models/
├── universal-sentence-encoder/ # Direct path
├── models/universal-sentence-encoder/ # @soulcraft/brainy-models structure
├── tfhub/universal-sentence-encoder/ # TensorFlow Hub structure
├── use/ # Short name
└── model.json # Root directory
```
## Cloud Run Deployment
For Google Cloud Run, use the embedded models strategy:
```dockerfile
FROM node:24-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Copy models during build
RUN if [ -d "./node_modules/@soulcraft/brainy-models" ]; then \
mkdir -p /app/models && \
cp -r ./node_modules/@soulcraft/brainy-models/models/* /app/models/; \
fi
ENV BRAINY_MODELS_PATH=/app/models
ENV PORT=8080
EXPOSE 8080
CMD ["node", "dist/server.js"]
```
Deploy with:
```bash
gcloud run deploy brainy-app \
--source . \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--memory 2Gi \
--cpu 1
```
## AWS Lambda/ECS Deployment
Similar approach works for AWS services:
```dockerfile
FROM public.ecr.aws/lambda/nodejs:24
# Copy models during build
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN mkdir -p /var/task/models && \
cp -r ./node_modules/@soulcraft/brainy-models/models/* /var/task/models/
ENV BRAINY_MODELS_PATH=/var/task/models
CMD ["index.handler"]
```
## Verification
Your application logs should show:
```
✅ Found model at custom path: /app/models/universal-sentence-encoder/model.json
✅ Successfully loaded model from custom directory
Using custom model path for Docker/production deployment
```
Instead of:
```
⚠️ Local model not found. Falling back to remote model loading.
```
## Benefits
1. **Faster startup**: No model download time
2. **Offline deployment**: Works without internet access
3. **Predictable performance**: No network dependency
4. **Smaller runtime image**: Can exclude dev dependencies
5. **Security**: No external network calls required
## Troubleshooting
### Models not found
1. Check the environment variable is set: `echo $BRAINY_MODELS_PATH`
2. Verify models directory exists: `ls -la /app/models`
3. Check model structure: `find /app/models -name "model.json"`
### Memory issues
Models require approximately 500MB of RAM. Ensure your container has sufficient memory:
```yaml
deploy:
resources:
limits:
memory: 2G
```
### Build failures
If `@soulcraft/brainy-models` is not available during build:
1. Ensure it's in `dependencies`, not `devDependencies`
2. Use `npm ci --only=production` instead of `npm install`
3. Check the package is properly published and accessible