603 lines
12 KiB
Markdown
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**
|