Skip to content

Nexus Server - Docker Deployment Guide

This guide covers deploying Nexus RPC Server using Docker and Docker Compose, including deployment to Google Cloud Platform.

Table of Contents

Quick Start

Prerequisites

# Install Docker
# macOS: brew install --cask docker
# Linux: curl -fsSL https://get.docker.com | sh
# Verify installation
docker --version
docker-compose --version

Run with Docker Compose

# 1. Copy environment file
cp .env.docker.example .env

# 2. Edit .env with your configuration
# At minimum, set a secure API key:
#   NEXUS_API_KEY=$(openssl rand -hex 32)

# 3. Start the server
docker-compose up -d

# 4. Test the server
curl http://localhost:2026/health

That's it! The server is now running at http://localhost:2026.

Local Development

Build and Run

# Build the image
docker build -t nexus-server:latest .

# Run with default settings
docker run -d \
  --name nexus-server \
  -p 2026:2026 \
  -v nexus-data:/app/data \
  nexus-server:latest

# Run with API key
docker run -d \
  --name nexus-server \
  -p 2026:2026 \
  -e NEXUS_API_KEY="mysecretkey" \
  -v nexus-data:/app/data \
  nexus-server:latest

Development with Docker Compose

# Start in foreground (see logs)
docker-compose up

# Start in background
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down

# Stop and remove volumes (⚠️ deletes data)
docker-compose down -v

Hot Reload Development

For development with code changes, mount the source directory:

docker run -d \
  --name nexus-dev \
  -p 2026:2026 \
  -v $(pwd)/src:/app/src \
  -v nexus-data:/app/data \
  -e NEXUS_API_KEY="devkey" \
  nexus-server:latest

Production Deployment

  1. Prepare Environment
# Generate secure API key
export API_KEY=$(openssl rand -hex 32)
echo "Save this: $API_KEY"

# Create .env file
cat > .env <<EOF
PORT=2026
NEXUS_API_KEY=$API_KEY
NEXUS_BACKEND=local
EOF
  1. Optional: Configure GCS Backend
# Add to .env
cat >> .env <<EOF
NEXUS_BACKEND=gcs
NEXUS_GCS_BUCKET_NAME=your-nexus-bucket
NEXUS_GCS_PROJECT_ID=your-project-id
GCS_CREDENTIALS_PATH=./gcs-credentials.json
GOOGLE_APPLICATION_CREDENTIALS=/app/gcs-credentials.json
EOF

# Place your GCS credentials
cp /path/to/service-account-key.json ./gcs-credentials.json
  1. Deploy
# Start services
docker-compose up -d

# Verify health
curl http://localhost:2026/health

# View logs
docker-compose logs -f nexus-server

Production Best Practices

1. Use Multi-Stage Build

The Dockerfile already uses multi-stage builds for optimal image size:

FROM python:3.11-slim as builder
# ... build stage ...

FROM python:3.11-slim
# ... production stage (smaller) ...

2. Set Resource Limits

Create docker-compose.prod.yml:

version: '3.8'

services:
  nexus-server:
    extends:
      file: docker-compose.yml
      service: nexus-server
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 4G
        reservations:
          cpus: '1.0'
          memory: 2G
    restart: always

Run with:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

3. Enable Log Rotation

Already configured in docker-compose.yml:

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

4. Regular Backups

# Backup data volume
docker run --rm \
  -v nexus-data:/data \
  -v $(pwd)/backups:/backup \
  ubuntu tar czf /backup/nexus-data-$(date +%Y%m%d).tar.gz /data

# Restore from backup
docker run --rm \
  -v nexus-data:/data \
  -v $(pwd)/backups:/backup \
  ubuntu tar xzf /backup/nexus-data-20250119.tar.gz -C /

5. Health Monitoring

# Check container health
docker inspect --format='{{.State.Health.Status}}' nexus-server

# Automated health check with restart
docker-compose up -d
# Docker automatically restarts unhealthy containers

GCP Deployment with Docker

# Build locally and deploy
./deploy-gcp-docker.sh \
  --project-id your-project-id \
  --api-key $(openssl rand -hex 32) \
  --build-local

# Use pre-built image from GCR
./deploy-gcp-docker.sh \
  --project-id your-project-id \
  --api-key mysecret \
  --registry gcr.io/your-project-id

# With GCS backend
./deploy-gcp-docker.sh \
  --project-id your-project-id \
  --api-key mysecret \
  --gcs-bucket your-nexus-bucket \
  --machine-type e2-standard-2 \
  --build-local

Method 2: Manual GCP Deployment

Step 1: Build and Push Image

# Set project
export PROJECT_ID="your-project-id"
gcloud config set project $PROJECT_ID

# Build image
docker build -t gcr.io/$PROJECT_ID/nexus-server:latest .

# Configure Docker for GCR
gcloud auth configure-docker gcr.io

# Push to Google Container Registry
docker push gcr.io/$PROJECT_ID/nexus-server:latest

Step 2: Create VM with Container

# Generate API key
export API_KEY=$(openssl rand -hex 32)

# Create instance
gcloud compute instances create-with-container nexus-docker \
  --zone=us-central1-a \
  --machine-type=e2-medium \
  --boot-disk-size=50GB \
  --container-image=gcr.io/$PROJECT_ID/nexus-server:latest \
  --container-restart-policy=always \
  --container-env=NEXUS_API_KEY=$API_KEY \
  --container-mount-host-path=mount-path=/app/data,host-path=/var/lib/nexus,mode=rw \
  --tags=nexus-server \
  --scopes=cloud-platform

# Create firewall rule
gcloud compute firewall-rules create allow-nexus-2026 \
  --allow=tcp:2026 \
  --target-tags=nexus-server

Step 3: Get External IP and Test

# Get external IP
EXTERNAL_IP=$(gcloud compute instances describe nexus-docker \
  --zone=us-central1-a \
  --format='get(networkInterfaces[0].accessConfigs[0].natIP)')

# Test
curl http://$EXTERNAL_IP:2026/health

Method 3: Google Cloud Run (Serverless)

# Deploy to Cloud Run (automatic scaling)
gcloud run deploy nexus-server \
  --image=gcr.io/$PROJECT_ID/nexus-server:latest \
  --platform=managed \
  --region=us-central1 \
  --allow-unauthenticated \
  --port=2026 \
  --memory=2Gi \
  --cpu=2 \
  --set-env-vars=NEXUS_API_KEY=$API_KEY,NEXUS_BACKEND=gcs,NEXUS_GCS_BUCKET_NAME=your-bucket

# Get URL
gcloud run services describe nexus-server \
  --region=us-central1 \
  --format='value(status.url)'

Note: Cloud Run is better for variable workloads. For constant traffic, Compute Engine with containers is more cost-effective.

Configuration

Environment Variables

Variable Description Default
NEXUS_HOST Server bind host 0.0.0.0
NEXUS_PORT Server port 2026
NEXUS_DATA_DIR Data directory path /app/data
NEXUS_API_KEY API authentication key none
NEXUS_BACKEND Storage backend (local or gcs) local
NEXUS_GCS_BUCKET_NAME GCS bucket name -
NEXUS_GCS_PROJECT_ID GCP project ID -
GOOGLE_APPLICATION_CREDENTIALS Path to GCS credentials -

Volume Mounts

Container Path Purpose Recommended Host Path
/app/data Nexus metadata and local storage Named volume or /var/lib/nexus
/app/gcs-credentials.json GCS service account key (optional) ./gcs-credentials.json

Management

View Logs

# Docker Compose
docker-compose logs -f

# Docker directly
docker logs -f nexus-server

# Last 100 lines
docker logs --tail 100 nexus-server

# GCP VM
gcloud compute ssh nexus-docker --zone=us-central1-a \
  --command='sudo docker logs -f $(sudo docker ps -q)'

Restart Container

# Docker Compose
docker-compose restart

# Docker directly
docker restart nexus-server

# GCP VM
gcloud compute ssh nexus-docker --zone=us-central1-a \
  --command='sudo docker restart $(sudo docker ps -q)'

Update to Latest Version

# Pull latest image
docker-compose pull

# Recreate containers
docker-compose up -d

# Or in one command
docker-compose pull && docker-compose up -d

Scale Horizontally (Load Balancing)

For high availability, run multiple instances behind a load balancer:

# docker-compose.scale.yml
version: '3.8'
services:
  nexus-server:
    # ... same config ...
    deploy:
      replicas: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - nexus-server

Execute Commands in Container

# Open shell
docker exec -it nexus-server /bin/bash

# Run nexus CLI command
docker exec nexus-server nexus ls /workspace

# Check Python version
docker exec nexus-server python --version

Troubleshooting

Container Won't Start

# Check logs
docker logs nexus-server

# Check if port is in use
lsof -i :2026

# Check container status
docker ps -a | grep nexus-server

# Inspect container
docker inspect nexus-server

Permission Issues

If you see permission errors:

# Fix volume permissions
docker run --rm -v nexus-data:/data alpine chown -R 1000:1000 /data

# Or run as root (not recommended for production)
docker run -d \
  --name nexus-server \
  --user root \
  -p 2026:2026 \
  nexus-server:latest

Out of Memory

# Check container resource usage
docker stats nexus-server

# Increase memory limit
docker run -d \
  --name nexus-server \
  --memory="4g" \
  --memory-swap="4g" \
  -p 2026:2026 \
  nexus-server:latest

GCS Authentication Issues

# Verify credentials file
docker exec nexus-server cat /app/gcs-credentials.json

# Test GCS access
docker exec nexus-server python -c "
from google.cloud import storage
client = storage.Client()
buckets = list(client.list_buckets())
print(f'Accessible buckets: {len(buckets)}')
"

Rebuild Image Without Cache

# Full rebuild
docker build --no-cache -t nexus-server:latest .

# Or with docker-compose
docker-compose build --no-cache

Performance Tuning

Multi-Stage Build Optimization

Already implemented in the Dockerfile. The builder stage is ~1GB, but the final image is only ~300MB.

Use BuildKit

# Enable BuildKit for faster builds
export DOCKER_BUILDKIT=1
docker build -t nexus-server:latest .

# Or with docker-compose
DOCKER_BUILDKIT=1 docker-compose build

Layer Caching

The Dockerfile is optimized for caching: 1. System dependencies (rarely change) 2. Python dependencies (change occasionally) 3. Application code (changes frequently)

Resource Limits

Set appropriate limits based on your workload:

# docker-compose.yml
deploy:
  resources:
    limits:
      cpus: '2.0'
      memory: 4G
    reservations:
      cpus: '0.5'
      memory: 1G

Security Best Practices

  1. Never commit .env files - Add to .gitignore
  2. Use secrets management - For production, use Docker secrets or GCP Secret Manager
  3. Run as non-root - Already configured in Dockerfile (USER nexus)
  4. Scan images regularly - Use docker scan nexus-server:latest
  5. Keep images updated - Rebuild regularly to get security patches
  6. Use minimal base images - Using python:3.11-slim (not alpine for better compatibility)
  7. Restrict network access - Use firewall rules and security groups
  8. Enable TLS - Use reverse proxy (nginx, Caddy) for HTTPS

Cost Optimization

Stop Containers When Not in Use

# Stop but keep data
docker-compose stop

# Start again
docker-compose start

# GCP: Stop VM to save compute costs (keeps disk)
gcloud compute instances stop nexus-docker --zone=us-central1-a

Use Spot/Preemptible Instances

For GCP deployment, use preemptible instances (up to 80% cheaper):

gcloud compute instances create-with-container nexus-docker \
  --preemptible \
  --container-image=gcr.io/$PROJECT_ID/nexus-server:latest \
  # ... other options ...

Resource Limits

Set appropriate CPU/memory limits to avoid over-provisioning:

deploy:
  resources:
    limits:
      cpus: '1.0'  # Adjust based on your needs
      memory: 2G

References