# Deployment Guide: LCBP3-DMS

---

**Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System)
**Version:** 1.6.0
**Last Updated:** 2025-12-02
**Owner:** Operations Team
**Status:** Active

---

## 📋 Overview

This guide provides step-by-step instructions for deploying the LCBP3-DMS system on QNAP Container Station using Docker Compose with Blue-Green deployment strategy.

### Deployment Strategy

- **Platform:** QNAP TS-473A with Container Station
- **Orchestration:** Docker Compose
- **Deployment Method:** Blue-Green Deployment
- **Zero Downtime:** Yes
- **Rollback Capability:** Instant rollback via NGINX switch

---

## 🎯 Prerequisites

### Hardware Requirements

| Component  | Minimum Specification      |
| ---------- | -------------------------- |
| CPU        | 4 cores @ 2.0 GHz          |
| RAM        | 16 GB                      |
| Storage    | 500 GB SSD (System + Data) |
| Network    | 1 Gbps Ethernet            |
| QNAP Model | TS-473A or equivalent      |

### Software Requirements

| Software          | Version | Purpose                  |
| ----------------- | ------- | ------------------------ |
| QNAP QTS          | 5.x+    | Operating System         |
| Container Station | 3.x+    | Docker Management        |
| Docker            | 20.10+  | Container Runtime        |
| Docker Compose    | 2.x+    | Multi-container Orchestr |

### Network Requirements

- Static IP address for QNAP server
- Domain name (e.g., `lcbp3-dms.example.com`)
- SSL certificate (Let's Encrypt or commercial)
- Firewall rules:
  - Port 80 (HTTP → HTTPS redirect)
  - Port 443 (HTTPS)
  - Port 22 (SSH for management)

---

## 🏗️ Infrastructure Setup

### 1. Directory Structure

Create the following directory structure on QNAP:

```bash
# SSH into QNAP
ssh admin@qnap-ip

# Create base directory
mkdir -p /volume1/lcbp3

# Create blue-green environments
mkdir -p /volume1/lcbp3/blue
mkdir -p /volume1/lcbp3/green

# Create shared directories
mkdir -p /volume1/lcbp3/shared/uploads
mkdir -p /volume1/lcbp3/shared/logs
mkdir -p /volume1/lcbp3/shared/backups

# Create persistent volumes
mkdir -p /volume1/lcbp3/volumes/mariadb-data
mkdir -p /volume1/lcbp3/volumes/redis-data
mkdir -p /volume1/lcbp3/volumes/elastic-data

# Create NGINX proxy directory
mkdir -p /volume1/lcbp3/nginx-proxy

# Set permissions
chmod -R 755 /volume1/lcbp3
chown -R admin:administrators /volume1/lcbp3
```

**Final Structure:**

```
/volume1/lcbp3/
├── blue/                    # Blue environment
│   ├── docker-compose.yml
│   ├── .env.production
│   └── nginx.conf
│
├── green/                   # Green environment
│   ├── docker-compose.yml
│   ├── .env.production
│   └── nginx.conf
│
├── nginx-proxy/             # Main reverse proxy
│   ├── docker-compose.yml
│   ├── nginx.conf
│   └── ssl/
│       ├── cert.pem
│       └── key.pem
│
├── shared/                  # Shared across blue/green
│   ├── uploads/
│   ├── logs/
│   └── backups/
│
├── volumes/                 # Persistent data
│   ├── mariadb-data/
│   ├── redis-data/
│   └── elastic-data/
│
├── scripts/                 # Deployment scripts
│   ├── deploy.sh
│   ├── rollback.sh
│   └── health-check.sh
│
└── current                  # File containing "blue" or "green"
```

### 2. SSL Certificate Setup

```bash
# Option 1: Let's Encrypt (Recommended)
# Install certbot on QNAP
opkg install certbot

# Generate certificate
certbot certonly --standalone \
  -d lcbp3-dms.example.com \
  --email admin@example.com \
  --agree-tos

# Copy to nginx-proxy
cp /etc/letsencrypt/live/lcbp3-dms.example.com/fullchain.pem \
   /volume1/lcbp3/nginx-proxy/ssl/cert.pem
cp /etc/letsencrypt/live/lcbp3-dms.example.com/privkey.pem \
   /volume1/lcbp3/nginx-proxy/ssl/key.pem

# Option 2: Commercial Certificate
# Upload cert.pem and key.pem to /volume1/lcbp3/nginx-proxy/ssl/
```

---

## 📝 Configuration Files

### 1. Environment Variables (.env.production)

Create `.env.production` in both `blue/` and `green/` directories:

```bash
# File: /volume1/lcbp3/blue/.env.production
# DO NOT commit this file to Git!

# Application
NODE_ENV=production
APP_NAME=LCBP3-DMS
APP_URL=https://lcbp3-dms.example.com

# Database
DB_HOST=lcbp3-mariadb
DB_PORT=3306
DB_USERNAME=lcbp3_user
DB_PASSWORD=<CHANGE_ME_STRONG_PASSWORD>
DB_DATABASE=lcbp3_dms
DB_POOL_SIZE=20

# Redis
REDIS_HOST=lcbp3-redis
REDIS_PORT=6379
REDIS_PASSWORD=<CHANGE_ME_STRONG_PASSWORD>
REDIS_DB=0

# JWT Authentication
JWT_SECRET=<CHANGE_ME_RANDOM_64_CHAR_STRING>
JWT_EXPIRES_IN=8h
JWT_REFRESH_EXPIRES_IN=7d

# File Storage
UPLOAD_PATH=/app/uploads
MAX_FILE_SIZE=52428800
ALLOWED_FILE_TYPES=.pdf,.doc,.docx,.xls,.xlsx,.dwg,.zip

# Email (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USERNAME=<YOUR_EMAIL>
SMTP_PASSWORD=<YOUR_APP_PASSWORD>
SMTP_FROM=noreply@example.com

# Elasticsearch
ELASTICSEARCH_NODE=http://lcbp3-elasticsearch:9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=<CHANGE_ME>

# Rate Limiting
THROTTLE_TTL=60
THROTTLE_LIMIT=100

# Logging
LOG_LEVEL=info
LOG_FILE_PATH=/app/logs

# ClamAV (Virus Scanning)
CLAMAV_HOST=lcbp3-clamav
CLAMAV_PORT=3310
```

### 2. Docker Compose - Blue Environment

```yaml
# File: /volume1/lcbp3/blue/docker-compose.yml
version: '3.8'

services:
  backend:
    image: lcbp3-backend:latest
    container_name: lcbp3-blue-backend
    restart: unless-stopped
    env_file:
      - .env.production
    volumes:
      - /volume1/lcbp3/shared/uploads:/app/uploads
      - /volume1/lcbp3/shared/logs:/app/logs
    depends_on:
      - mariadb
      - redis
      - elasticsearch
    networks:
      - lcbp3-network
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  frontend:
    image: lcbp3-frontend:latest
    container_name: lcbp3-blue-frontend
    restart: unless-stopped
    environment:
      - NEXT_PUBLIC_API_URL=https://lcbp3-dms.example.com/api
    depends_on:
      - backend
    networks:
      - lcbp3-network
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:3000']
      interval: 30s
      timeout: 10s
      retries: 3

  mariadb:
    image: mariadb:11.8
    container_name: lcbp3-mariadb
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - /volume1/lcbp3/volumes/mariadb-data:/var/lib/mysql
    networks:
      - lcbp3-network
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --max_connections=200
      --innodb_buffer_pool_size=2G
    healthcheck:
      test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: lcbp3-redis
    restart: unless-stopped
    command: >
      redis-server
      --requirepass ${REDIS_PASSWORD}
      --appendonly yes
      --appendfsync everysec
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
    volumes:
      - /volume1/lcbp3/volumes/redis-data:/data
    networks:
      - lcbp3-network
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 10s
      timeout: 3s
      retries: 3

  elasticsearch:
    image: elasticsearch:8.11.0
    container_name: lcbp3-elasticsearch
    restart: unless-stopped
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=true
      - ELASTIC_PASSWORD=${ELASTICSEARCH_PASSWORD}
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g"
    volumes:
      - /volume1/lcbp3/volumes/elastic-data:/usr/share/elasticsearch/data
    networks:
      - lcbp3-network
    healthcheck:
      test: ['CMD-SHELL', 'curl -f http://localhost:9200/_cluster/health || exit 1']
      interval: 30s
      timeout: 10s
      retries: 5

networks:
  lcbp3-network:
    name: lcbp3-blue-network
    driver: bridge
```

### 3. Docker Compose - NGINX Proxy

```yaml
# File: /volume1/lcbp3/nginx-proxy/docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: lcbp3-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
      - /volume1/lcbp3/shared/logs/nginx:/var/log/nginx
    networks:
      - lcbp3-blue-network
      - lcbp3-green-network
    healthcheck:
      test: ['CMD', 'nginx', '-t']
      interval: 30s
      timeout: 10s
      retries: 3

networks:
  lcbp3-blue-network:
    external: true
  lcbp3-green-network:
    external: true
```

### 4. NGINX Configuration

```nginx
# File: /volume1/lcbp3/nginx-proxy/nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    client_max_body_size 50M;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss;

    # Upstream backends (switch between blue/green)
    upstream backend {
        server lcbp3-blue-backend:3000 max_fails=3 fail_timeout=30s;
        keepalive 32;
    }

    upstream frontend {
        server lcbp3-blue-frontend:3000 max_fails=3 fail_timeout=30s;
        keepalive 32;
    }

    # HTTP to HTTPS redirect
    server {
        listen 80;
        server_name lcbp3-dms.example.com;
        return 301 https://$server_name$request_uri;
    }

    # HTTPS server
    server {
        listen 443 ssl http2;
        server_name lcbp3-dms.example.com;

        # SSL configuration
        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/key.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # Security headers
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;

        # Frontend (Next.js)
        location / {
            proxy_pass http://frontend;
            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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_cache_bypass $http_upgrade;
        }

        # Backend API
        location /api {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            # Timeouts for file uploads
            proxy_connect_timeout 300s;
            proxy_send_timeout 300s;
            proxy_read_timeout 300s;
        }

        # Health check endpoint (no logging)
        location /health {
            proxy_pass http://backend/health;
            access_log off;
        }

        # Static files caching
        location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
            proxy_pass http://frontend;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
}
```

---

## 🚀 Initial Deployment

### Step 1: Prepare Docker Images

```bash
# Build images (on development machine)
cd /path/to/lcbp3/backend
docker build -t lcbp3-backend:1.0.0 .
docker tag lcbp3-backend:1.0.0 lcbp3-backend:latest

cd /path/to/lcbp3/frontend
docker build -t lcbp3-frontend:1.0.0 .
docker tag lcbp3-frontend:1.0.0 lcbp3-frontend:latest

# Save images to tar files
docker save lcbp3-backend:latest | gzip > lcbp3-backend-latest.tar.gz
docker save lcbp3-frontend:latest | gzip > lcbp3-frontend-latest.tar.gz

# Transfer to QNAP
scp lcbp3-backend-latest.tar.gz admin@qnap-ip:/volume1/lcbp3/
scp lcbp3-frontend-latest.tar.gz admin@qnap-ip:/volume1/lcbp3/

# Load images on QNAP
ssh admin@qnap-ip
cd /volume1/lcbp3
docker load < lcbp3-backend-latest.tar.gz
docker load < lcbp3-frontend-latest.tar.gz
```

### Step 2: Initialize Database

```bash
# Start MariaDB only
cd /volume1/lcbp3/blue
docker-compose up -d mariadb

# Wait for MariaDB to be ready
docker exec lcbp3-mariadb mysqladmin ping -h localhost

# Run migrations
docker-compose up -d backend
docker exec lcbp3-blue-backend npm run migration:run

# Seed initial data (if needed)
docker exec lcbp3-blue-backend npm run seed
```

### Step 3: Start Blue Environment

```bash
cd /volume1/lcbp3/blue

# Start all services
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker-compose logs -f

# Wait for health checks
sleep 30

# Test health endpoint
curl http://localhost:3000/health
```

### Step 4: Start NGINX Proxy

```bash
cd /volume1/lcbp3/nginx-proxy

# Create networks (if not exist)
docker network create lcbp3-blue-network
docker network create lcbp3-green-network

# Start NGINX
docker-compose up -d

# Test NGINX configuration
docker exec lcbp3-nginx nginx -t

# Check NGINX logs
docker logs lcbp3-nginx
```

### Step 5: Set Current Environment

```bash
# Mark blue as current
echo "blue" > /volume1/lcbp3/current
```

### Step 6: Verify Deployment

```bash
# Test HTTPS endpoint
curl -k https://lcbp3-dms.example.com/health

# Test API
curl -k https://lcbp3-dms.example.com/api/health

# Check all containers
docker ps --filter "name=lcbp3"

# Check logs for errors
docker-compose -f /volume1/lcbp3/blue/docker-compose.yml logs --tail=100
```

---

## 🔄 Blue-Green Deployment Process

### Deployment Script

```bash
# File: /volume1/lcbp3/scripts/deploy.sh
#!/bin/bash

set -e  # Exit on error

# Configuration
LCBP3_DIR="/volume1/lcbp3"
CURRENT=$(cat $LCBP3_DIR/current)
TARGET=$([[ "$CURRENT" == "blue" ]] && echo "green" || echo "blue")

echo "========================================="
echo "LCBP3-DMS Blue-Green Deployment"
echo "========================================="
echo "Current environment: $CURRENT"
echo "Target environment:  $TARGET"
echo "========================================="

# Step 1: Backup database
echo "[1/9] Creating database backup..."
BACKUP_FILE="$LCBP3_DIR/shared/backups/db-backup-$(date +%Y%m%d-%H%M%S).sql"
docker exec lcbp3-mariadb mysqldump -u root -p${DB_PASSWORD} lcbp3_dms > $BACKUP_FILE
gzip $BACKUP_FILE
echo "✓ Backup created: $BACKUP_FILE.gz"

# Step 2: Pull latest images
echo "[2/9] Pulling latest Docker images..."
cd $LCBP3_DIR/$TARGET
docker-compose pull
echo "✓ Images pulled"

# Step 3: Update configuration
echo "[3/9] Updating configuration..."
# Copy .env if changed
if [ -f "$LCBP3_DIR/.env.production.new" ]; then
    cp $LCBP3_DIR/.env.production.new $LCBP3_DIR/$TARGET/.env.production
    echo "✓ Configuration updated"
fi

# Step 4: Start target environment
echo "[4/9] Starting $TARGET environment..."
docker-compose up -d
echo "✓ $TARGET environment started"

# Step 5: Wait for services to be ready
echo "[5/9] Waiting for services to be healthy..."
sleep 10

# Check backend health
for i in {1..30}; do
    if docker exec lcbp3-${TARGET}-backend curl -f http://localhost:3000/health > /dev/null 2>&1; then
        echo "✓ Backend is healthy"
        break
    fi
    if [ $i -eq 30 ]; then
        echo "✗ Backend health check failed!"
        docker-compose logs backend
        exit 1
    fi
    sleep 2
done

# Step 6: Run database migrations
echo "[6/9] Running database migrations..."
docker exec lcbp3-${TARGET}-backend npm run migration:run
echo "✓ Migrations completed"

# Step 7: Switch NGINX to target environment
echo "[7/9] Switching NGINX to $TARGET..."
sed -i "s/lcbp3-${CURRENT}-backend/lcbp3-${TARGET}-backend/g" $LCBP3_DIR/nginx-proxy/nginx.conf
sed -i "s/lcbp3-${CURRENT}-frontend/lcbp3-${TARGET}-frontend/g" $LCBP3_DIR/nginx-proxy/nginx.conf
docker exec lcbp3-nginx nginx -t
docker exec lcbp3-nginx nginx -s reload
echo "✓ NGINX switched to $TARGET"

# Step 8: Verify new environment
echo "[8/9] Verifying new environment..."
sleep 5
if curl -f -k https://lcbp3-dms.example.com/health > /dev/null 2>&1; then
    echo "✓ New environment is responding"
else
    echo "✗ New environment verification failed!"
    echo "Rolling back..."
    ./rollback.sh
    exit 1
fi

# Step 9: Stop old environment
echo "[9/9] Stopping $CURRENT environment..."
cd $LCBP3_DIR/$CURRENT
docker-compose down
echo "✓ $CURRENT environment stopped"

# Update current pointer
echo "$TARGET" > $LCBP3_DIR/current

echo "========================================="
echo "✓ Deployment completed successfully!"
echo "Active environment: $TARGET"
echo "========================================="

# Send notification (optional)
# /scripts/send-notification.sh "Deployment completed: $TARGET is now active"
```

### Rollback Script

```bash
# File: /volume1/lcbp3/scripts/rollback.sh
#!/bin/bash

set -e

LCBP3_DIR="/volume1/lcbp3"
CURRENT=$(cat $LCBP3_DIR/current)
PREVIOUS=$([[ "$CURRENT" == "blue" ]] && echo "green" || echo "blue")

echo "========================================="
echo "LCBP3-DMS Rollback"
echo "========================================="
echo "Current: $CURRENT"
echo "Rolling back to: $PREVIOUS"
echo "========================================="

# Switch NGINX back
echo "[1/3] Switching NGINX to $PREVIOUS..."
sed -i "s/lcbp3-${CURRENT}-backend/lcbp3-${PREVIOUS}-backend/g" $LCBP3_DIR/nginx-proxy/nginx.conf
sed -i "s/lcbp3-${CURRENT}-frontend/lcbp3-${PREVIOUS}-frontend/g" $LCBP3_DIR/nginx-proxy/nginx.conf
docker exec lcbp3-nginx nginx -s reload
echo "✓ NGINX switched"

# Start previous environment if stopped
echo "[2/3] Ensuring $PREVIOUS environment is running..."
cd $LCBP3_DIR/$PREVIOUS
docker-compose up -d
sleep 10
echo "✓ $PREVIOUS environment is running"

# Verify
echo "[3/3] Verifying rollback..."
if curl -f -k https://lcbp3-dms.example.com/health > /dev/null 2>&1; then
    echo "✓ Rollback successful"
    echo "$PREVIOUS" > $LCBP3_DIR/current
else
    echo "✗ Rollback verification failed!"
    exit 1
fi

echo "========================================="
echo "✓ Rollback completed"
echo "Active environment: $PREVIOUS"
echo "========================================="
```

### Make Scripts Executable

```bash
chmod +x /volume1/lcbp3/scripts/deploy.sh
chmod +x /volume1/lcbp3/scripts/rollback.sh
```

---

## 📋 Deployment Checklist

### Pre-Deployment

- [ ] Backup current database
- [ ] Tag Docker images with version
- [ ] Update `.env.production` if needed
- [ ] Review migration scripts
- [ ] Notify stakeholders of deployment window
- [ ] Verify SSL certificate validity (> 30 days)
- [ ] Check disk space (> 20% free)
- [ ] Review recent error logs

### During Deployment

- [ ] Pull latest Docker images
- [ ] Start target environment (blue/green)
- [ ] Run database migrations
- [ ] Verify health checks pass
- [ ] Switch NGINX proxy
- [ ] Verify application responds correctly
- [ ] Check for errors in logs
- [ ] Monitor performance metrics

### Post-Deployment

- [ ] Monitor logs for 30 minutes
- [ ] Check performance metrics
- [ ] Verify all features working
- [ ] Test critical user flows
- [ ] Stop old environment
- [ ] Update deployment log
- [ ] Notify stakeholders of completion
- [ ] Archive old Docker images

---

## 🔍 Troubleshooting

### Common Issues

#### 1. Container Won't Start

```bash
# Check logs
docker logs lcbp3-blue-backend

# Check resource usage
docker stats

# Restart container
docker restart lcbp3-blue-backend
```

#### 2. Database Connection Failed

```bash
# Check MariaDB is running
docker ps | grep mariadb

# Test connection
docker exec lcbp3-mariadb mysql -u lcbp3_user -p -e "SELECT 1"

# Check environment variables
docker exec lcbp3-blue-backend env | grep DB_
```

#### 3. NGINX 502 Bad Gateway

```bash
# Check backend is running
curl http://localhost:3000/health

# Check NGINX configuration
docker exec lcbp3-nginx nginx -t

# Check NGINX logs
docker logs lcbp3-nginx

# Reload NGINX
docker exec lcbp3-nginx nginx -s reload
```

#### 4. Migration Failed

```bash
# Check migration status
docker exec lcbp3-blue-backend npm run migration:show

# Revert last migration
docker exec lcbp3-blue-backend npm run migration:revert

# Re-run migrations
docker exec lcbp3-blue-backend npm run migration:run
```

---

## 📊 Monitoring

### Health Checks

```bash
# Backend health
curl https://lcbp3-dms.example.com/health

# Database health
docker exec lcbp3-mariadb mysqladmin ping

# Redis health
docker exec lcbp3-redis redis-cli ping

# All containers status
docker ps --filter "name=lcbp3" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
```

### Performance Monitoring

```bash
# Container resource usage
docker stats --no-stream

# Disk usage
df -h /volume1/lcbp3

# Database size
docker exec lcbp3-mariadb mysql -u root -p -e "
  SELECT table_schema AS 'Database',
         ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
  FROM information_schema.tables
  WHERE table_schema = 'lcbp3_dms'
  GROUP BY table_schema;"
```

---

## 🔐 Security Best Practices

1. **Change Default Passwords:** Update all passwords in `.env.production`
2. **SSL/TLS:** Always use HTTPS in production
3. **Firewall:** Only expose ports 80, 443, and 22 (SSH)
4. **Regular Updates:** Keep Docker images updated
5. **Backup Encryption:** Encrypt database backups
6. **Access Control:** Limit SSH access to specific IPs
7. **Secrets Management:** Never commit `.env` files to Git
8. **Log Monitoring:** Review logs daily for suspicious activity

---

## 📚 Related Documentation

- [Environment Setup Guide](04-02-environment-setup.md)
- [Backup & Recovery](04-04-backup-recovery.md)
- [Monitoring & Alerting](04-03-monitoring-alerting.md)
- [Maintenance Procedures](04-05-maintenance-procedures.md)
- [ADR-015: Deployment Infrastructure](../05-decisions/ADR-015-deployment-infrastructure.md)

---

**Version:** 1.6.0
**Last Updated:** 2025-12-02
**Next Review:** 2026-06-01
