# DEPLOYMENT.md — Sistem MAT KOIPB (Docker · Ubuntu Server) Panduan deploy aplikasi **Kehadiran & Cabutan Bertuah MAT KOIPB** menggunakan Docker pada server Ubuntu. Stack: **Nginx + PHP 8.4-FPM (Laravel) + MySQL 8** — semua dalam container, tiada pemasangan PHP/MySQL pada host. > UI guna CDN + CSS statik (`public/css/koipb.css`) — **tiada langkah build Node/Vite**. --- ## Keperluan Server | Komponen | Minimum | Disyorkan | |---|---|---| | OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | | CPU | 2 core | 4 core | | RAM | 2 GB | 4 GB | | Storage | 10 GB | 20 GB | | Docker | 24.x | Latest stable | | Docker Compose | 2.x | Latest stable | Untuk 150–200 peserta, server kecil sudah memadai. --- ## Struktur Fail Docker ``` /srv/koipb/ ├── .env # disalin dari .env.docker.example (JANGAN commit) ├── .env.docker.example # templat ├── Dockerfile # imej PHP-FPM (Laravel) ├── docker-compose.yml # dev (nginx + app + mysql) ├── docker-compose.prod.yml # override production ├── docker/ │ ├── entrypoint.sh # wait-db, composer, key:generate, migrate, seed, cache │ ├── nginx/default.conf │ └── php/{php.ini, php-dev.ini, php-prod.ini} └── ... (kod Laravel) ``` --- ## Langkah Deployment Pertama Kali ### 1. Persediaan server ```bash sudo apt update && sudo apt upgrade -y curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER newgrp docker docker --version && docker compose version ``` ### 2. Dapatkan kod ```bash sudo mkdir -p /srv/koipb && sudo chown $USER:$USER /srv/koipb cd /srv/koipb git clone . ``` ### 3. Konfigurasi environment ```bash cp .env.docker.example .env nano .env ``` Wajib tukar: | Pemboleh ubah | Nota | |---|---| | `APP_KEY` | Biar kosong — entrypoint jana automatik kali pertama | | `APP_URL` | cth `https://mat.koipb.gov.my` | | `APP_PORT` | `80` (atau di belakang reverse proxy) | | `DB_PASSWORD` | password user `koipb` | | `DB_ROOT_PASSWORD` | password root MySQL container | | `SEED_DEMO` | `true` = isi 200 anggota + 21 hadiah contoh; `false` = data kosong (import sendiri) | > `DB_HOST` mesti kekal `mysql` (nama service container). ### 4. Logo ```bash # Letak logo sebenar (kalau belum): cp /path/ke/logo.jpg public/images/logo-koipb.jpg ``` ### 5. Bina & jalankan (production) ```bash docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build ``` Entrypoint akan automatik: tunggu MySQL → composer install → `key:generate` → `migrate --force` → seed peranan/pengguna (+ demo jika `SEED_DEMO=true`) → cache config/route/view. Semak: ```bash docker compose ps docker compose logs -f app # tunggu "✅ Aplikasi bersedia." ``` Buka `http://` (atau `APP_URL`). --- ## Login Default Kata laluan semua: **`password`** — **WAJIB tukar selepas log masuk pertama** (atau ubah dalam `RoleUserSeeder` sebelum deploy). | Peranan | E-mel | |---|---| | Admin | `admin@koipb.test` | | Petugas Kaunter | `kaunter@koipb.test` | | Petugas Cabutan | `cabutan@koipb.test` | --- ## Operasi Harian ```bash # Status / log docker compose ps docker compose logs -f app # Masuk shell artisan docker compose exec app php artisan # Backup database (penting sebelum & selepas event!) docker compose exec mysql sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" koipb_mat' > backup-$(date +%F-%H%M).sql # Restore cat backup.sql | docker compose exec -T mysql sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" koipb_mat' # Henti / mula semula docker compose -f docker-compose.yml -f docker-compose.prod.yml down docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d ``` > Data MySQL kekal dalam named volume **`koipb_db_data`** walaupun container dipadam. `docker compose down` (tanpa `-v`) **tidak** memadam data. **Jangan** guna `down -v` semasa event. --- ## Kemaskini Versi (Redeploy) ```bash cd /srv/koipb git pull docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # Entrypoint akan migrate + cache semula automatik. ``` --- ## Reverse Proxy + HTTPS (pilihan) Jika ada Nginx/Caddy di host atau sijil SSL, set `APP_PORT` kepada port dalaman (cth `8080`) dan proksi ke port itu. Contoh blok Nginx host: ```nginx server { server_name mat.koipb.gov.my; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; } } ``` Kemudian pasang sijil melalui `certbot --nginx`. --- ## Penyelesaian Masalah | Masalah | Tindakan | |---|---| | `app` asyik restart | `docker compose logs app` — biasanya MySQL belum sedia atau `.env` salah | | `419 Page Expired` / log masuk gagal | `APP_KEY` kosong — `docker compose exec app php artisan key:generate --force` lalu `docker compose restart app` | | 502 Bad Gateway | container `app` belum naik / belum siap `composer install`; tunggu log "Aplikasi bersedia" | | Tukar `.env` tak berkesan | `docker compose exec app php artisan config:clear` dan restart | | Reset data untuk event baharu | Log masuk admin → **Tetapan & Reset**, atau `docker compose exec app php artisan migrate:fresh --seed --force` |