Docker Deployment
Run NotebookLM MCP Server in a Docker container for isolated, reproducible deployments.
Quick Start
Using Docker Compose (Recommended)
# Build and start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
Using Docker CLI
# Build image
docker build -t notebooklm-mcp .
# Run container
docker run -d \
--name notebooklm-mcp \
--restart unless-stopped \
-p 3000:3000 \
-p 6080:6080 \
-v notebooklm-data:/data \
-e HEADLESS=true \
-e STEALTH_ENABLED=true \
-e NOTEBOOKLM_UI_LOCALE=fr \
notebooklm-mcp
Ports
| Port | Description |
|---|---|
| 3000 | HTTP REST API |
| 6080 | noVNC web interface (for authentication) |
First-Time Authentication via noVNC
Docker includes a noVNC server for visual browser access, required for initial Google authentication.
Step 1: Open noVNC
Open in your browser:
http://localhost:6080/vnc.html
Step 2: Trigger Authentication
curl -X POST http://localhost:3000/setup-auth \
-H "Content-Type: application/json" \
-d '{"show_browser": true}'
Step 3: Login in noVNC
- The Chromium browser appears in the noVNC window
- Complete Google login
- Authentication is saved automatically
- Browser closes when done
Verify Authentication
curl http://localhost:3000/health
# → {"success":true,"data":{"authenticated":true,...}}
Alternative: Copy Existing Credentials
If you've already authenticated locally:
# Copy from local machine to container
docker cp ~/.local/share/notebooklm-mcp/. notebooklm-mcp:/data/
# Restart container
docker restart notebooklm-mcp
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
HTTP_PORT | 3000 | HTTP server port |
HTTP_HOST | 0.0.0.0 | HTTP server host |
HEADLESS | true | Run browser headless |
STEALTH_ENABLED | true | Enable anti-detection |
NOTEBOOKLM_DATA_DIR | /data | Data directory path |
NOTEBOOKLM_UI_LOCALE | fr | UI language (fr/en) |
AUTO_LOGIN_ENABLED | false | Enable auto-login |
ENABLE_VNC | true | Enable noVNC server |
NOVNC_PORT | 6080 | noVNC web port |
Custom Configuration
Edit docker-compose.yml to customize:
environment:
- HEADLESS=true
- NOTEBOOKLM_UI_LOCALE=en
- AUTO_LOGIN_ENABLED=true
Data Persistence
All data is stored in the /data volume:
/data/
├── library.json # Notebook library
├── chrome_profile/ # Chrome profile (Google session)
├── browser_state/ # Browser state backup
├── accounts.json # Account configuration
├── accounts/ # Per-account data
│ └── account-xxx/
│ ├── credentials.enc.json
│ ├── quota.json
│ └── state.json
└── encryption.key # Encryption key
Backup
# Backup data volume
docker run --rm \
-v notebooklm-mcp-data:/data:ro \
-v $(pwd):/backup \
alpine tar czf /backup/notebooklm-backup.tar.gz -C /data .
# Restore
docker run --rm \
-v notebooklm-mcp-data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/notebooklm-backup.tar.gz -C /data
NAS Deployment (Synology, QNAP)
Build and Export
# On your local machine
npm run build
docker build -t notebooklm-mcp:latest .
docker save notebooklm-mcp:latest | gzip > notebooklm-mcp.tar.gz
Upload and Deploy
# Upload to NAS
scp notebooklm-mcp.tar.gz user@nas:/volume1/docker/
# SSH to NAS and load
ssh user@nas
docker load < /volume1/docker/notebooklm-mcp.tar.gz
# Run container
docker run -d \
--name notebooklm-mcp \
--restart unless-stopped \
-p 3000:3000 \
-p 6080:6080 \
-v /volume1/docker/notebooklm/data:/data \
-e HEADLESS=true \
-e STEALTH_ENABLED=true \
-e NOTEBOOKLM_UI_LOCALE=fr \
notebooklm-mcp:latest
Authenticate via noVNC
- Open
http://nas-ip:6080/vnc.html - Run setup-auth command
- Complete Google login in VNC window
Resource Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| Memory | 512 MB | 2 GB |
| CPU | 1 core | 2 cores |
| Disk | 500 MB | 2 GB |
Chromium uses significant memory. Adjust limits in docker-compose.yml:
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 1G
Troubleshooting
Container won't start
# Check logs
docker logs notebooklm-mcp
# Check container status
docker ps -a
Browser issues
If Chromium fails to launch:
- Ensure sufficient memory (minimum 512MB)
- Check logs for errors
- Try rebuilding:
docker build --no-cache -t notebooklm-mcp .
noVNC not accessible
- Verify port 6080 is exposed
- Check firewall rules
- Verify container is running:
docker ps
Authentication issues
# Check health endpoint
curl http://localhost:3000/health
# If not authenticated, use noVNC method above
Permission issues
# Fix volume permissions
docker run --rm -v notebooklm-mcp-data:/data alpine chown -R 1000:1000 /data
Production Deployment
With Reverse Proxy (nginx)
server {
listen 80;
server_name notebooklm.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
}
# noVNC (restrict access!)
location /vnc {
proxy_pass http://localhost:6080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
# Add authentication here!
}
}
Security Considerations
- Don't expose port 6080 publicly - noVNC gives browser access
- Use a reverse proxy with authentication for production
- Regular backups of the data volume
- Monitor container health using the healthcheck endpoint
Architecture
Docker Container
├── Node.js HTTP Server (port 3000)
├── Xvfb (:99) - Virtual display
├── x11vnc - VNC server
├── websockify/noVNC (port 6080) - Web VNC
└── Chromium browser
User → noVNC (6080) → VNC → Xvfb → Chromium
User → HTTP API (3000) → Node.js → Chromium