Files
Alberto-Audrix 32a36cceff
CI / lint-and-test (push) Canceled after 0s
first commit
2026-07-28 08:55:05 +07:00

603 lines
12 KiB
Markdown

# Docker Deployment Guide
Complete guide for deploying Dashboard Solusi AI Peternakan Ayam using Docker containers.
## 📋 Table of Contents
- [Architecture](#architecture)
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Deployment](#deployment)
- [Management](#management)
- [Troubleshooting](#troubleshooting)
## 🏗️ Architecture
The application runs in 3 Docker containers:
```
┌─────────────────────────────────────────────────┐
│ Host Server │
│ │
│ ┌────────────────┐ ┌──────────────────┐ │
│ │ Frontend │ │ Backend │ │
│ │ (Nginx) │◄────►│ (Node.js) │ │
│ │ Port 80 │ │ Port 5001 │ │
│ └────────────────┘ └──────────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────┐ │
│ │ │ Database │ │
│ └──────────────►│ (PostgreSQL) │ │
│ │ Port 5432 │ │
│ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
```
### Container Details
| Container | Image | Port | Description |
| ------------ | ------------------ | ---------- | -------------------------- |
| **frontend** | nginx:alpine | 80 | React app served by Nginx |
| **backend** | node:18-alpine | 5001 | Express API server |
| **database** | postgres:16-alpine | 15432→5432 | PostgreSQL database server |
### Network Communication
- Frontend → Backend: Internal Docker network (`dashboard-network`)
- Backend → Database: Internal Docker network (`dashboard-network`)
- Client → Frontend: HTTP port 80 (or 5002 in dev)
- Host → Database: TCP port 15432 (for DBeaver, psql, backups)
## 📦 Prerequisites
### Required Software
- **Docker**: v20.10+ ([Install](https://docs.docker.com/get-docker/))
- **Docker Compose**: v2.0+ ([Install](https://docs.docker.com/compose/install/))
Check versions:
```bash
docker --version
docker-compose --version
```
### Server Requirements
- **OS**: Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
- **RAM**: Minimum 2GB, Recommended 4GB+
- **Disk**: Minimum 10GB free space
- **CPU**: 2+ cores recommended
### Ports
Ensure these ports are available:
- **80** or **5002**: Frontend (HTTP)
- **5001**: Backend API
- **15432**: PostgreSQL (for local access, DBeaver, backups)
Check port availability:
```bash
sudo lsof -i :80
sudo lsof -i :5001
sudo lsof -i :15432
```
## 🚀 Quick Start
### 1. Clone Repository
```bash
git clone <repository-url>
cd dashboard-solusi-ai-peternakan-ayam
```
### 2. Configure Environment (Optional)
```bash
# Copy and edit if you need custom settings
cp .env.example .env
```
### 3. Build and Start Containers
```bash
docker-compose up -d --build
```
This will:
- ✅ Build frontend and backend images
- ✅ Create containers
- ✅ Initialize database
- ✅ Start all services
### 4. Verify Deployment
```bash
# Check container status
docker-compose ps
# Check logs
docker-compose logs -f
# Test frontend
curl http://localhost
# Test backend
curl http://localhost/api/health
```
### 5. Access Application
Open browser: **http://your-server-ip**
## ⚙️ Configuration
### Environment Variables
#### Frontend (.env.example)
```env
# API URL - Uses nginx proxy in Docker
VITE_API_URL=/api
```
#### Backend Environment Variables
These are set in docker-compose.yml:
```yaml
environment:
- NODE_ENV=production
- PORT=5001
- DB_HOST=database
- DB_PORT=5432
- DB_USER=${DB_USER:-dashboard_user}
- DB_PASSWORD=${DB_PASSWORD:-change_this_password}
- DB_NAME=${DB_NAME:-dashboard_db}
- DB_SSL=false
```
### Custom Configuration
**1. Create environment file:**
```bash
cp .env.example .env
cp backend/.env.example backend/.env
```
**2. Edit docker-compose.yml:**
Change ports:
```yaml
services:
frontend:
ports:
- '8080:80' # Change from 80 to 8080
```
Change database credentials:
```yaml
# Create .env file in project root:
DB_USER=my_user
DB_PASSWORD=my_secure_password
DB_NAME=my_database
```
## 🚢 Deployment
### Development Deployment
```bash
# Build and start with logs
docker-compose up --build
# Press Ctrl+C to stop
```
### Production Deployment
```bash
# Build and start in detached mode
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop viewing logs (Ctrl+C, containers keep running)
```
### Update Deployment
When code changes:
```bash
# Pull latest code
git pull origin main
# Rebuild and restart
docker-compose down
docker-compose up -d --build
```
### Zero-Downtime Update
```bash
# Build new images
docker-compose build
# Restart services one by one
docker-compose up -d --no-deps --build backend
docker-compose up -d --no-deps --build frontend
```
## 🔧 Management
### Container Management
```bash
# Start all containers
docker-compose start
# Stop all containers
docker-compose stop
# Restart all containers
docker-compose restart
# Stop and remove containers
docker-compose down
# Stop and remove containers + volumes
docker-compose down -v
```
### View Logs
```bash
# All containers
docker-compose logs -f
# Specific container
docker-compose logs -f backend
docker-compose logs -f frontend
# Last 100 lines
docker-compose logs --tail=100
# Since timestamp
docker-compose logs --since 2025-12-22T10:00:00
```
### Execute Commands in Container
```bash
# Backend shell
docker-compose exec backend sh
# Frontend shell
docker-compose exec frontend sh
# Database shell (PostgreSQL)
docker-compose exec database psql -U dashboard_user -d dashboard_db
# Run seed in backend
docker-compose exec backend node database/seed-postgres.js
```
### Database Management
```bash
# Backup database (recommended)
./scripts/backup-postgres.sh
# Manual backup
docker-compose exec database sh -c \
'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
| gzip > backup-$(date +%Y%m%d).sql.gz
# Restore database
./scripts/restore-postgres-local.sh --reset backups/dashboard_db-YYYYMMDD.sql.gz
# Query database
docker-compose exec database psql -U dashboard_user -d dashboard_db -c "SELECT * FROM cycles;"
# Connect with psql from host
psql -h localhost -p 15432 -U dashboard_user -d dashboard_db
```
### Health Checks
```bash
# Check container health
docker-compose ps
# Expected output:
# NAME STATUS
# dashboard-database Up (healthy)
# dashboard-backend Up (healthy)
# dashboard-frontend Up (healthy)
# Manual health checks
curl http://localhost:5002/health # Backend
curl http://localhost:5002/api/cycles # API test
# Database health
docker-compose exec database pg_isready -U dashboard_user
```
## 🐛 Troubleshooting
### Container Won't Start
**Problem:** Container exits immediately
```bash
# Check logs
docker-compose logs backend
docker-compose logs frontend
# Common causes:
# - Port already in use
# - Missing dependencies
# - Configuration error
```
**Solution:**
```bash
# Remove and rebuild
docker-compose down
docker-compose up --build
```
### Port Conflicts
**Problem:** Port 80 or 5001 already in use
```bash
# Find process using port
sudo lsof -i :80
sudo lsof -i :5001
# Kill process
sudo kill -9 <PID>
# Or change port in docker-compose.yml
```
### Database Not Persisting
**Problem:** Data lost after restart
```bash
# Check volume
docker volume ls | grep db-data
docker volume inspect dashboard-solusi-ai-peternakan-ayam_db-data
# Check database is accessible
docker-compose exec database psql -U dashboard_user -d dashboard_db -c "SELECT COUNT(*) FROM cycles;"
```
**Solution:**
```bash
# Make sure you're not using -v flag when stopping
docker-compose down # Preserves volumes
# NOT: docker-compose down -v # This deletes volumes!
# Restart containers
docker-compose up -d
```
### Frontend Can't Connect to Backend
**Problem:** API requests fail with CORS or connection errors
**Check:**
```bash
# Test backend directly
curl http://localhost:5001/health
# Check nginx proxy config
docker-compose exec frontend cat /etc/nginx/conf.d/default.conf
# Check network
docker network ls
docker network inspect peternakan-network
```
**Solution:**
```bash
# Verify both containers are on same network
docker-compose down
docker-compose up -d
```
### Out of Disk Space
**Problem:** Build fails with "no space left on device"
```bash
# Check disk usage
df -h
# Clean Docker
docker system prune -a
docker volume prune
# Remove unused images
docker image prune -a
```
### Database Connection Errors
**Problem:** Backend can't connect to database
```bash
# Check database container is running and healthy
docker-compose ps database
# Check logs
docker-compose logs database
docker-compose logs backend
# Verify connection from backend
docker-compose exec backend sh -c 'psql -h database -U $DB_USER -d $DB_NAME -c "SELECT 1"'
# Restart services
docker-compose restart database backend
```
### Container Memory Issues
**Problem:** Container crashes with OOM
```bash
# Check memory usage
docker stats
# Add memory limits in docker-compose.yml:
services:
backend:
mem_limit: 512m
mem_reservation: 256m
```
## 📊 Monitoring
### Resource Usage
```bash
# Real-time stats
docker stats
# Container processes
docker-compose top
```
### Logs Analysis
```bash
# Search logs
docker-compose logs | grep ERROR
docker-compose logs | grep "Failed to"
# Export logs
docker-compose logs > application.log
```
## 🔒 Security
### Production Recommendations
1. **Use HTTPS:**
- Add reverse proxy (Nginx/Apache) with SSL
- Get certificate from Let's Encrypt
2. **Firewall:**
```bash
# Allow only necessary ports
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```
3. **Update regularly:**
```bash
# Update base images
docker-compose pull
docker-compose up -d
```
4. **Secure database:**
```bash
# Use strong passwords in production .env
DB_PASSWORD=your_very_strong_password_here
# Enable SSL for production
DB_SSL=true
# Block external database access (only allow from Docker network)
# Edit docker-compose.yml: remove or restrict ports section for database
```
## 🔄 Backup & Restore
### Backup
Use the provided script:
```bash
./scripts/backup-postgres.sh
```
This creates a compressed SQL dump in `./backups/dashboard_db-YYYYMMDD-HHMMSS.sql.gz`
**Manual backup:**
```bash
#!/bin/bash
# Manual backup example
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
docker-compose exec -T database sh -c \
'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" --no-owner --no-acl' \
| gzip -c > "$BACKUP_DIR/dashboard_db-$DATE.sql.gz"
echo "Backup completed: $BACKUP_DIR/dashboard_db-$DATE.sql.gz"
```
### Restore
Use the provided script:
```bash
./scripts/restore-postgres-local.sh --reset backups/dashboard_db-YYYYMMDD-HHMMSS.sql.gz
```
This will:
1. Stop and remove local Docker volumes
2. Start fresh database
3. Restore from backup file
**Note:** The `--reset` flag is required to prevent mixing old and new data.
## 📚 Additional Resources
- [Docker Documentation](https://docs.docker.com/)
- [Docker Compose Documentation](https://docs.docker.com/compose/)
- [Nginx Documentation](https://nginx.org/en/docs/)
## 🆘 Support
For issues specific to Docker deployment:
1. Check logs: `docker-compose logs -f`
2. Verify configuration: `docker-compose config`
3. Check GitHub Issues
4. Contact support@cpsp.id
---
**Docker deployment guide by PT Cipta Pola Solusi Prima - 2025**