Newer
Older
cactus / CONTAINER_GUIDE.md
@agalyaramadoss agalyaramadoss on 16 Feb 10 KB added document

Cube Database - Docker & Podman Guide

Overview

Run Cube database in containers using Docker or Podman with full cluster support.

Quick Start

Docker

# Build and start 3-node cluster
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker-compose logs -f

Podman

# Build and start 3-node cluster
podman-compose up -d

# Check status
podman-compose ps

# View logs
podman-compose logs -f

Prerequisites

Docker

# Install Docker
# Ubuntu/Debian:
sudo apt-get install docker.io docker-compose

# macOS:
brew install docker docker-compose

# Verify
docker --version
docker-compose --version

Podman

# Install Podman
# Ubuntu/Debian:
sudo apt-get install podman podman-compose

# Fedora/RHEL:
sudo dnf install podman podman-compose

# macOS:
brew install podman podman-compose

# Verify
podman --version
podman-compose --version

Building the Image

Docker

# Build image
docker build -t cube-db:latest .

# Verify
docker images | grep cube-db

Podman

# Build image
podman build -t cube-db:latest .

# Verify
podman images | grep cube-db

Running Single Node

Docker

# Run single node
docker run -d \
  --name cube-node-1 \
  -p 8080:8080 \
  -e CUBE_NODE_ID=node-1 \
  -e JAVA_OPTS="-Xmx1G" \
  -v cube-data:/var/lib/cube/data \
  cube-db:latest

# Check logs
docker logs -f cube-node-1

# Check health
curl http://localhost:8080/api/v1/health

Podman

# Run single node
podman run -d \
  --name cube-node-1 \
  -p 8080:8080 \
  -e CUBE_NODE_ID=node-1 \
  -e JAVA_OPTS="-Xmx1G" \
  -v cube-data:/var/lib/cube/data:Z \
  cube-db:latest

# Check logs
podman logs -f cube-node-1

# Check health
curl http://localhost:8080/api/v1/health

Running 3-Node Cluster

Docker Compose

docker-compose.yml is already configured. Just run:

# Start cluster
docker-compose up -d

# View status
docker-compose ps

# Expected output:
#     Name              State    Ports
# --------------------------------------------
# cube-node-1    Up      0.0.0.0:8080->8080/tcp
# cube-node-2    Up      0.0.0.0:8081->8080/tcp
# cube-node-3    Up      0.0.0.0:8082->8080/tcp

# Check all are healthy
docker-compose ps | grep healthy

# View logs for all nodes
docker-compose logs -f

# View logs for specific node
docker-compose logs -f cube-node-1

Podman Compose

podman-compose.yml is configured for Podman:

# Start cluster
podman-compose up -d

# View status
podman-compose ps

# Check health
for port in 8080 8081 8082; do
  echo "Node on port $port:"
  curl -s http://localhost:$port/api/v1/health
done

# View logs
podman-compose logs -f

Connecting to the Cluster

Using CubeShell

# From host machine
./run-shell.sh --host localhost --port 8080

# Connect to all nodes
cube> CONNECT localhost 8080
cube> CONNECT localhost 8081
cube> CONNECT localhost 8082
cube> NODES

Using API

# Node 1
curl -X POST http://localhost:8080/api/v1/put \
  -H "Content-Type: application/json" \
  -d '{"key":"test","value":"hello"}'

# Node 2
curl http://localhost:8081/api/v1/get/test

# Node 3
curl http://localhost:8082/api/v1/get/test

Exec into Container

Docker:

# Enter container
docker exec -it cube-node-1 /bin/bash

# Inside container
cd /opt/cube-db
curl localhost:8080/api/v1/health

Podman:

# Enter container
podman exec -it cube-node-1 /bin/bash

# Inside container
cd /opt/cube-db
curl localhost:8080/api/v1/health

Environment Variables

Variable Default Description
CUBE_NODE_ID node-1 Unique node identifier
CUBE_HOST 0.0.0.0 Listen address
CUBE_PORT 8080 API port
CUBE_DATA_DIR /var/lib/cube/data Data directory
CUBE_HINTS_DIR /var/lib/cube/hints Hints directory
JAVA_OPTS -Xmx1G -Xms512M JVM options

Custom Configuration

docker run -d \
  --name cube-custom \
  -p 9090:9090 \
  -e CUBE_NODE_ID=custom-node \
  -e CUBE_PORT=9090 \
  -e JAVA_OPTS="-Xmx2G -Xms1G" \
  cube-db:latest

Volume Management

Docker

# List volumes
docker volume ls | grep cube

# Inspect volume
docker volume inspect cube-node-1-data

# Backup volume
docker run --rm \
  -v cube-node-1-data:/data \
  -v $(pwd):/backup \
  ubuntu tar czf /backup/cube-node-1-backup.tar.gz /data

# Restore volume
docker run --rm \
  -v cube-node-1-data:/data \
  -v $(pwd):/backup \
  ubuntu tar xzf /backup/cube-node-1-backup.tar.gz -C /

# Remove volume (WARNING: deletes data)
docker volume rm cube-node-1-data

Podman

# List volumes
podman volume ls | grep cube

# Inspect volume
podman volume inspect cube-node-1-data

# Backup volume
podman run --rm \
  -v cube-node-1-data:/data:Z \
  -v $(pwd):/backup:Z \
  ubuntu tar czf /backup/cube-node-1-backup.tar.gz /data

# Restore volume
podman run --rm \
  -v cube-node-1-data:/data:Z \
  -v $(pwd):/backup:Z \
  ubuntu tar xzf /backup/cube-node-1-backup.tar.gz -C /

# Remove volume
podman volume rm cube-node-1-data

Cluster Operations

Stop Cluster

Docker:

docker-compose stop

Podman:

podman-compose stop

Restart Cluster

Docker:

docker-compose restart

Podman:

podman-compose restart

Remove Cluster (keeps volumes)

Docker:

docker-compose down

Podman:

podman-compose down

Remove Everything (including volumes)

Docker:

docker-compose down -v

Podman:

podman-compose down -v

Scaling the Cluster

Add Node 4

Edit docker-compose.yml or podman-compose.yml:

  cube-node-4:
    build: .
    container_name: cube-node-4
    hostname: cube-node-4
    environment:
      - CUBE_NODE_ID=node-4
      - CUBE_HOST=cube-node-4
      - CUBE_PORT=8080
    ports:
      - "8083:8080"
    volumes:
      - cube-node-4-data:/var/lib/cube/data:Z
      - cube-node-4-hints:/var/lib/cube/hints:Z
    networks:
      - cube-cluster

Then:

docker-compose up -d
# or
podman-compose up -d

Monitoring

Health Checks

# Check all nodes
for port in 8080 8081 8082; do
  echo "Node $port:"
  curl -s http://localhost:$port/api/v1/health | jq
done

# Output:
# {
#   "status": "UP",
#   "database": "Cube DB",
#   "version": "1.0.0"
# }

Statistics

# Get stats from each node
for port in 8080 8081 8082; do
  echo "Node $port stats:"
  curl -s http://localhost:$port/api/v1/stats | jq
done

Container Stats

Docker:

docker stats cube-node-1 cube-node-2 cube-node-3

Podman:

podman stats cube-node-1 cube-node-2 cube-node-3

Logs

Docker:

# All nodes
docker-compose logs -f

# Specific node
docker logs -f cube-node-1

# Last 100 lines
docker logs --tail 100 cube-node-1

# Since timestamp
docker logs --since 2024-01-01T00:00:00 cube-node-1

Podman:

# All nodes
podman-compose logs -f

# Specific node
podman logs -f cube-node-1

# Last 100 lines
podman logs --tail 100 cube-node-1

Testing Node Recovery

Simulate Node Failure

Docker:

# Stop node 3
docker stop cube-node-3

# Write data while node 3 is down
curl -X POST http://localhost:8080/api/v1/put \
  -H "Content-Type: application/json" \
  -d '{"key":"test:recovery","value":"data during outage"}'

# Restart node 3
docker start cube-node-3

# Wait 10 seconds for hint replay
sleep 10

# Verify data on node 3
curl http://localhost:8082/api/v1/get/test:recovery

Podman:

# Stop node 3
podman stop cube-node-3

# Write data
curl -X POST http://localhost:8080/api/v1/put \
  -H "Content-Type: application/json" \
  -d '{"key":"test:recovery","value":"data during outage"}'

# Restart node 3
podman start cube-node-3

# Wait for hint replay
sleep 10

# Verify
curl http://localhost:8082/api/v1/get/test:recovery

Production Deployment

Resource Limits

Add to docker-compose.yml:

services:
  cube-node-1:
    # ... existing config ...
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

Logging

Configure JSON logging:

services:
  cube-node-1:
    # ... existing config ...
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

Networking

Use host networking for better performance:

docker run -d \
  --name cube-node-1 \
  --network host \
  -e CUBE_PORT=8080 \
  cube-db:latest

Troubleshooting

Container won't start

# Check logs
docker logs cube-node-1

# Common issues:
# - Port already in use
# - Volume permission issues
# - Out of memory

Can't connect between nodes

# Check network
docker network inspect cube_cube-cluster

# Ensure all containers are on same network
docker network connect cube_cube-cluster cube-node-1

Volume permission issues (Podman)

# Add :Z flag to volumes for SELinux
-v cube-data:/var/lib/cube/data:Z

Out of memory

# Increase heap size
-e JAVA_OPTS="-Xmx2G -Xms1G"

Podman-Specific Features

Rootless Containers

# Run without root
podman run -d \
  --name cube-node-1 \
  -p 8080:8080 \
  cube-db:latest

# Check user
podman exec cube-node-1 whoami
# Output: cubedb (non-root)

Pods

Create a pod for all nodes:

# Create pod
podman pod create --name cube-cluster -p 8080-8082:8080

# Run nodes in pod
podman run -d --pod cube-cluster \
  --name cube-node-1 \
  -e CUBE_NODE_ID=node-1 \
  cube-db:latest

# List pods
podman pod ps

SystemD Integration

# Generate systemd unit
podman generate systemd --new --name cube-node-1 \
  > ~/.config/systemd/user/cube-node-1.service

# Enable and start
systemctl --user enable cube-node-1
systemctl --user start cube-node-1

Summary

Feature Docker Podman
Multi-node cluster
Volume persistence
Health checks
Rootless
SystemD integration
Pods

Both work great! Choose based on your preference:

  • Docker: Industry standard, great tooling
  • Podman: Rootless, daemonless, pod support

Quick Reference

# Build
docker build -t cube-db .

# Run single node
docker run -d -p 8080:8080 cube-db

# Run cluster
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker logs -f cube-node-1

# Stop cluster
docker-compose down

# Clean up
docker-compose down -v

Your Cube database is now containerized! 🐳