Skip to main content

Overview

Docker Compose provides the easiest way to deploy OpenSight with all required services. This guide covers both production deployment and development setup.

Prerequisites

1

Install Docker

Install Docker Engine 24.0 or later:
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Verify installation
docker --version
2

Install Docker Compose

Docker Compose is included with Docker Desktop. For Linux servers:
# Verify installation
docker compose version
Expected output: Docker Compose version v2.20.0 or later
3

Clone the repository

git clone https://github.com/yourusername/opensight.git
cd opensight

Production Deployment

Full Stack Configuration

The production docker-compose.yml deploys all services:
docker/docker-compose.yml
version: '3.8'

services:
  web:
    build:
      context: ..
      dockerfile: docker/Dockerfile.web
    ports:
      - "3000:3000"
    env_file: ../.env
    environment:
      - NODE_ENV=production
    depends_on:
      - api
    restart: unless-stopped

  api:
    build:
      context: ..
      dockerfile: docker/Dockerfile.api
    ports:
      - "4000:4000"
    env_file: ../.env
    environment:
      - NODE_ENV=production
    depends_on:
      - postgres
      - redis
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: opensight
      POSTGRES_PASSWORD: opensight
      POSTGRES_DB: opensight
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U opensight"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:
  redisdata:

Deploy Production Stack

1

Configure environment variables

Create your .env file from the example:
cp .env.example .env
Edit the .env file with your production settings. At minimum, update:
.env
# Database (use internal service name for Docker)
DATABASE_URL=postgresql://opensight:opensight@postgres:5432/opensight

# Redis (use internal service name for Docker)
UPSTASH_REDIS_REST_URL=redis://redis:6379

# Generate secure secrets
JWT_SECRET=your-secure-64-character-random-string-here
JWT_REFRESH_SECRET=your-secure-64-character-refresh-string-here

# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:4000
API_PORT=4000

# Frontend Configuration
NEXT_PUBLIC_APP_URL=http://localhost:3000
FRONTEND_URL=http://localhost:3000
See Environment Variables for complete reference.
2

Build and start services

docker compose -f docker/docker-compose.yml up -d
Expected output:
[+] Running 6/6
 ✔ Network opensight_default      Created
 ✔ Volume "opensight_pgdata"      Created
 ✔ Volume "opensight_redisdata"   Created
 ✔ Container opensight-postgres-1 Started
 ✔ Container opensight-redis-1    Started
 ✔ Container opensight-api-1      Started
 ✔ Container opensight-web-1      Started
3

Run database migrations

After the API container starts, run migrations:
docker compose -f docker/docker-compose.yml exec api npm run db:migrate
4

Verify deployment

Check that all services are running:
docker compose -f docker/docker-compose.yml ps
All services should show Up status with healthy checks passing:
NAME                    STATUS                    PORTS
opensight-web-1         Up 2 minutes              0.0.0.0:3000->3000/tcp
opensight-api-1         Up 2 minutes              0.0.0.0:4000->4000/tcp
opensight-postgres-1    Up 2 minutes (healthy)    0.0.0.0:5432->5432/tcp
opensight-redis-1       Up 2 minutes (healthy)    0.0.0.0:6379->6379/tcp
5

Access the application

Open your browser and navigate to:

Development Setup

Development Configuration

For local development, use docker-compose.dev.yml which runs only PostgreSQL and Redis:
docker/docker-compose.dev.yml
version: '3.8'

services:
  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: opensight
      POSTGRES_PASSWORD: opensight
      POSTGRES_DB: opensight
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U opensight"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:
  redisdata:

Start Development Environment

1

Start database services

npm run docker:up
# Or manually:
docker compose -f docker/docker-compose.dev.yml up -d
2

Install dependencies

npm install
3

Set up database

npm run db:setup
This runs migrations and seeds the database.
4

Start development servers

npm run dev
This starts:

Docker Commands Reference

Production Commands

# Start all services
docker compose -f docker/docker-compose.yml up -d

# Start with build (rebuild images)
docker compose -f docker/docker-compose.yml up -d --build

# View logs (all services)
docker compose -f docker/docker-compose.yml logs -f

# View logs (specific service)
docker compose -f docker/docker-compose.yml logs -f api

# Check service status
docker compose -f docker/docker-compose.yml ps

# Stop all services
docker compose -f docker/docker-compose.yml down

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

# Restart a specific service
docker compose -f docker/docker-compose.yml restart api

# Execute command in running container
docker compose -f docker/docker-compose.yml exec api npm run db:migrate

Development Commands

# Start development stack (PostgreSQL + Redis)
npm run docker:up
# Or: docker compose -f docker/docker-compose.dev.yml up -d

# Stop development stack
npm run docker:down
# Or: docker compose -f docker/docker-compose.dev.yml down

# View logs
docker compose -f docker/docker-compose.dev.yml logs -f

# Check status
docker compose -f docker/docker-compose.dev.yml ps

Service Configuration

Port Mappings

ServiceContainer PortHost PortDescription
web30003000Next.js web application
api40004000Express API server
postgres54325432PostgreSQL database
redis63796379Redis cache
In production, you may want to avoid exposing PostgreSQL and Redis ports to the host. Remove the ports mapping for these services to keep them internal to the Docker network.

Volume Mounts

VolumeMount PointPurpose
pgdata/var/lib/postgresql/dataPostgreSQL data persistence
redisdata/dataRedis data persistence

Health Checks

Each service includes health checks for monitoring:
# PostgreSQL health check
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U opensight"]
  interval: 10s
  timeout: 5s
  retries: 5

# Redis health check
healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 10s
  timeout: 5s
  retries: 5

Troubleshooting

Services Won’t Start

docker compose -f docker/docker-compose.yml logs api
Ensure your .env file is properly configured:
cat .env | grep -v '^#' | grep -v '^$'
Ensure ports 3000, 4000, 5432, and 6379 are not in use:
sudo lsof -i :3000
sudo lsof -i :4000
sudo lsof -i :5432
sudo lsof -i :6379
Stop all services and remove containers:
docker compose -f docker/docker-compose.yml down
docker compose -f docker/docker-compose.yml up -d --build

Database Connection Issues

When running services in Docker, use the service name (e.g., postgres) instead of localhost in DATABASE_URL:
# Correct for Docker
DATABASE_URL=postgresql://opensight:opensight@postgres:5432/opensight

# Incorrect for Docker
DATABASE_URL=postgresql://opensight:opensight@localhost:5432/opensight

View Container Resource Usage

# Real-time stats
docker stats

# Disk usage
docker system df

# Volume inspection
docker volume ls
docker volume inspect opensight_pgdata

Production Best Practices

Use External Database

For production, consider using a managed PostgreSQL service (AWS RDS, Google Cloud SQL, etc.) instead of the containerized database.

Secure Secrets

Use Docker secrets or environment variable management services instead of plain .env files.

Enable HTTPS

Use a reverse proxy like Nginx or Traefik to handle SSL/TLS termination.

Monitor Resources

Set up monitoring with Prometheus, Grafana, or similar tools to track container health.

Remove Exposed Ports

For production security, modify docker-compose.yml to remove port mappings for internal services:
# Before (development)
postgres:
  ports:
    - "5432:5432"

# After (production)
postgres:
  # Remove ports mapping - only accessible via Docker network
  expose:
    - "5432"

Set Resource Limits

Add resource constraints to prevent services from consuming excessive resources:
services:
  api:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

Backup and Restore

Backup Database

# Create backup
docker compose -f docker/docker-compose.yml exec postgres pg_dump -U opensight opensight > backup-$(date +%Y%m%d).sql

# Backup with compression
docker compose -f docker/docker-compose.yml exec postgres pg_dump -U opensight opensight | gzip > backup-$(date +%Y%m%d).sql.gz

Restore Database

# Restore from backup
docker compose -f docker/docker-compose.yml exec -T postgres psql -U opensight opensight < backup.sql

# Restore from compressed backup
gunzip < backup.sql.gz | docker compose -f docker/docker-compose.yml exec -T postgres psql -U opensight opensight

Backup Volumes

# Backup PostgreSQL volume
docker run --rm -v opensight_pgdata:/data -v $(pwd):/backup alpine tar czf /backup/pgdata-backup.tar.gz -C /data .

# Backup Redis volume
docker run --rm -v opensight_redisdata:/data -v $(pwd):/backup alpine tar czf /backup/redisdata-backup.tar.gz -C /data .

Next Steps

Environment Variables

Configure all environment variables for your deployment

Self-Hosting Guide

Learn about architecture and deployment options

Build docs developers (and LLMs) love