diff --git a/.env.docker.example b/.env.docker.example index ff30631..df35e6c 100644 --- a/.env.docker.example +++ b/.env.docker.example @@ -1,11 +1,13 @@ # ───────────────────────────────────────────────────────────────────────────── -# KOIPB MAT — Templat .env untuk Docker (dev & Ubuntu server) +# KOIPB MAT — Templat env untuk Docker (dev & Ubuntu server) # -# cp .env.docker.example .env +# cp .env.docker.example .env.docker # # kemudian tukar SEMUA password di bawah # -# Fail .env ini dibaca oleh Laravel (env_file) DAN oleh Docker Compose -# untuk gantian ${DB_*} pada service mysql. +# PENTING: guna nama fail .env.docker (BUKAN .env) supaya tidak berlanggar +# dengan .env tempatan anda untuk `php artisan serve`. +# +# Fail ini dibaca oleh kedua-dua service (app & mysql) melalui env_file. # ───────────────────────────────────────────────────────────────────────────── APP_NAME="KOIPB MAT" @@ -14,22 +16,27 @@ APP_KEY= APP_DEBUG=false APP_URL=http://localhost -# Port nginx pada host (dev biasanya 8000; prod 80) +# Port nginx pada host (dev 8000; prod 80). Untuk tukar, hantar --env-file .env.docker APP_PORT=80 APP_LOCALE=ms APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=ms_MY -# ── Database (DB_HOST mesti "mysql" = nama service Docker) ──────────────────── +# ── Database — untuk Laravel (DB_HOST mesti "mysql" = nama service Docker) ──── DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 DB_DATABASE=koipb_mat DB_USERNAME=koipb DB_PASSWORD=tukar_password_ini -# Digunakan hanya untuk root MySQL dalam container (gantian ${DB_ROOT_PASSWORD}) -DB_ROOT_PASSWORD=tukar_root_password_ini + +# ── MySQL container — MESTI SAMA dengan DB_* di atas ───────────────────────── +# (MYSQL_USER TIDAK boleh "root" — guna "koipb") +MYSQL_DATABASE=koipb_mat +MYSQL_USER=koipb +MYSQL_PASSWORD=tukar_password_ini +MYSQL_ROOT_PASSWORD=tukar_root_password_ini # Seed data demo (200 anggota + 21 hadiah) pada deploy pertama? true/false SEED_DEMO=true diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 252b4c1..f0df449 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -25,7 +25,7 @@ Untuk 150–200 peserta, server kecil sudah memadai. ``` /srv/koipb/ -├── .env # disalin dari .env.docker.example (JANGAN commit) +├── .env.docker # disalin dari .env.docker.example (JANGAN commit) ├── .env.docker.example # templat ├── Dockerfile # imej PHP-FPM (Laravel) ├── docker-compose.yml # dev (nginx + app + mysql) @@ -62,10 +62,12 @@ git clone . ### 3. Konfigurasi environment ```bash -cp .env.docker.example .env -nano .env +cp .env.docker.example .env.docker +nano .env.docker ``` +> Guna nama fail **`.env.docker`** (bukan `.env`) supaya tidak berlanggar dengan `.env` tempatan untuk `php artisan serve`. + Wajib tukar: | Pemboleh ubah | Nota | @@ -73,11 +75,11 @@ Wajib tukar: | `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 | +| `DB_PASSWORD` **dan** `MYSQL_PASSWORD` | password user `koipb` — **mesti sama** | +| `MYSQL_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). +> `DB_HOST`/`MYSQL_*` jangan diubah namanya. `MYSQL_USER` mesti `koipb` (BUKAN `root` — MySQL menolaknya). ### 4. Logo @@ -89,7 +91,8 @@ 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 +docker compose --env-file .env.docker \ + -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. @@ -134,8 +137,8 @@ docker compose exec mysql sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" koip 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 +docker compose --env-file .env.docker -f docker-compose.yml -f docker-compose.prod.yml down +docker compose --env-file .env.docker -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. @@ -147,7 +150,7 @@ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d ```bash cd /srv/koipb git pull -docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build +docker compose --env-file .env.docker -f docker-compose.yml -f docker-compose.prod.yml up -d --build # Entrypoint akan migrate + cache semula automatik. ``` diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 330435b..7be088f 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -2,7 +2,8 @@ # KOIPB MAT — Docker Compose Production Override (Ubuntu Server) # # Penggunaan: -# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build +# docker compose --env-file .env.docker \ +# -f docker-compose.yml -f docker-compose.prod.yml up -d --build # # Perbezaan dari dev: # • APP_ENV=production, APP_DEBUG=false → config/route/view cache @@ -28,6 +29,7 @@ services: DB_PORT: "3306" volumes: - ./:/var/www/html + - ./.env.docker:/var/www/html/.env - ./docker/php/php.ini:/usr/local/etc/php/conf.d/99-koipb.ini:ro - ./docker/php/php-prod.ini:/usr/local/etc/php/conf.d/99-koipb-prod.ini:ro diff --git a/docker-compose.yml b/docker-compose.yml index 97daa2a..9dcdcdc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,14 +2,15 @@ # KOIPB MAT — Docker Compose (Development) # # Penggunaan: -# cp .env.docker.example .env # isi DB_PASSWORD / DB_ROOT_PASSWORD -# docker compose up -d --build +# cp .env.docker.example .env.docker # isi password +# docker compose --env-file .env.docker up -d --build # # Aplikasi : http://localhost:8000 # MySQL : service "mysql" (named volume koipb_db_data) # -# NOTA: .env yang sama dibaca oleh Laravel (env_file) DAN oleh Docker Compose -# untuk gantian ${DB_*} pada service mysql. Pastikan DB_HOST=mysql. +# NOTA: Docker guna .env.docker (BUKAN .env). Ini elak konflik dengan .env +# tempatan anda (yang mungkin DB_USERNAME=root untuk php artisan serve). +# MYSQL_USER TIDAK boleh "root" — sebab itu .env.docker guna "koipb". ############################################################################### name: koipb @@ -20,17 +21,15 @@ services: image: mysql:8.0 container_name: koipb_mysql restart: unless-stopped - environment: - MYSQL_DATABASE: ${DB_DATABASE:-koipb_mat} - MYSQL_USER: ${DB_USERNAME:-koipb} - MYSQL_PASSWORD: ${DB_PASSWORD:-secret} - MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret} + # Baca MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD / MYSQL_ROOT_PASSWORD + env_file: + - .env.docker volumes: - koipb_db_data:/var/lib/mysql ports: - "127.0.0.1:3307:3306" # akses dev dari host (elak conflict dgn MySQL tempatan 3306) healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_ROOT_PASSWORD:-rootsecret}"] + test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p\"$$MYSQL_ROOT_PASSWORD\" --silent"] interval: 10s timeout: 5s retries: 10 @@ -46,14 +45,16 @@ services: restart: unless-stopped working_dir: /var/www/html env_file: - - .env + - .env.docker environment: APP_ENV: local APP_DEBUG: "true" - DB_HOST: mysql # paksa ke container mysql, walau .env tersilap + DB_HOST: mysql # paksa ke container mysql, walau .env.docker tersilap DB_PORT: "3306" volumes: - ./:/var/www/html + # .env dalam container = .env.docker (elak .env tempatan root/1234 dibaca Laravel) + - ./.env.docker:/var/www/html/.env - ./docker/php/php.ini:/usr/local/etc/php/conf.d/99-koipb.ini:ro - ./docker/php/php-dev.ini:/usr/local/etc/php/conf.d/99-koipb-dev.ini:ro depends_on: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index a29febc..cf3da05 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -58,20 +58,25 @@ chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache 2 chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null || true # ── 3. Generate APP_KEY jika kosong ─────────────────────────────────────────── +# Fail .env dalam container = .env.docker (di-overlay melalui volume). if [ -z "${APP_KEY}" ]; then echo "🔑 Menjana APP_KEY..." php artisan key:generate --force fi -# Penting: env_file mungkin hantar APP_KEY="" (kosong) sebagai env var sebenar -# yang mengatasi nilai dalam .env. Baca semula dari .env & EXPORT supaya -# proses anak (migrate, config:cache, php-fpm) mewarisi kunci yang betul. +# env_file menyuntik APP_KEY (mungkin kosong) sebagai env var sebenar yang +# mengatasi nilai dalam fail. Baca semula dari .env & EXPORT supaya proses anak +# (migrate, config:cache, php-fpm) mewarisi kunci yang betul. if [ -f /var/www/html/.env ]; then FILE_KEY=$(grep -E '^APP_KEY=' /var/www/html/.env | head -1 | cut -d= -f2-) - if [ -n "${FILE_KEY}" ]; then - export APP_KEY="${FILE_KEY}" - fi + [ -n "${FILE_KEY}" ] && export APP_KEY="${FILE_KEY}" fi +# ── 3b. Bersihkan cache lama ────────────────────────────────────────────────── +# Penting: config.php basi (cth dari deploy lama) boleh mengatasi .env semasa. +php artisan config:clear 2>/dev/null || true +php artisan route:clear 2>/dev/null || true +php artisan view:clear 2>/dev/null || true + # ── 4. Migration + seed peranan & pengguna (idempotent) ─────────────────────── echo "🗄 Menjalankan migration..." php artisan migrate --force