From 874dbbe8e8bfd4fc4ce88e69f8861ae4a0d4b789 Mon Sep 17 00:00:00 2001 From: Power BI Dev Date: Sat, 2 May 2026 10:07:56 +0700 Subject: [PATCH] Add Docker and Coolify deployment setup Add the container configuration, environment templates, and storage settings needed to deploy SPOTA with Docker and Coolify. --- .dockerignore | 27 +++++++ .env.coolify.example | 14 ++++ .env.example | 17 +++++ .gitignore | 62 ++++++++++++++++ DOCKER.md | 74 +++++++++++++++++++ Dockerfile | 23 ++++++ Dockerfile.coolify | 31 ++++++++ docker-compose.coolify.yml | 49 ++++++++++++ docker-compose.yml | 51 +++++++++++++ docker/apache-vhost.conf | 13 ++++ .../mysql-init/00-import-spota-databases.sh | 33 +++++++++ docker/php.ini | 13 ++++ 12 files changed, 407 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.coolify.example create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 DOCKER.md create mode 100644 Dockerfile create mode 100644 Dockerfile.coolify create mode 100644 docker-compose.coolify.yml create mode 100644 docker-compose.yml create mode 100644 docker/apache-vhost.conf create mode 100644 docker/mysql-init/00-import-spota-databases.sh create mode 100644 docker/php.ini diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cec3a05 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,27 @@ +.git +.gitignore +spota_db/openfileslimit +spota_db +*.zip +*.rar +*.7z +*.tar +*.tar.gz +*.tgz +error_log +**/error_log +**/.DS_Store +index_gacor.php +index_gacor.html +cgi-bin +bekap +direktori-spn +pkm +rekomendasi-artikel +simpanghilir +sisesta +pedoman-old +files +files/** +!files/.gitkeep +img/curiga diff --git a/.env.coolify.example b/.env.coolify.example new file mode 100644 index 0000000..9bf2e30 --- /dev/null +++ b/.env.coolify.example @@ -0,0 +1,14 @@ +APP_URL=https://spota.example.com + +DB_USER=spota_user +DB_PASSWORD=change_this_database_password +DB_NAME=spota_spotadb +DB_SPOTA=spota_spotadb +DB_KONSULTASI=spota_konsultasi +DB_BIO=spota_spotadb +DB_DOSEN=spota_spotadb +SERVICE_DB_NAME=spota_spotadb + +MYSQL_ROOT_PASSWORD=change_this_root_password +PHP_DISPLAY_ERRORS=0 +FILES_STORAGE_PATH=/var/www/html/files diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..38ad7cc --- /dev/null +++ b/.env.example @@ -0,0 +1,17 @@ +APP_PORT=8080 +APP_URL=http://localhost:8080 + +DB_HOST=db +DB_PORT=3307 +DB_USER=spota_user +DB_PASSWORD=spota_password +DB_NAME=spota_spotadb +DB_SPOTA=spota_spotadb +DB_KONSULTASI=spota_konsultasi +DB_BIO=spota_spotadb +DB_DOSEN=spota_spotadb +SERVICE_DB_NAME=spota_spotadb + +MYSQL_ROOT_PASSWORD=root_password +PHP_DISPLAY_ERRORS=1 +FILES_STORAGE_PATH=/var/www/html/files diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01a4654 --- /dev/null +++ b/.gitignore @@ -0,0 +1,62 @@ +# Environment and secrets +.env +.env.* +!.env.example +!.env.coolify.example + +# Dependencies / generated packages +/vendor/ +node_modules/ +npm-debug.log* +yarn-error.log* +composer.lock +package-lock.json + +# Runtime uploads and user-generated files +/files/ +/files/** +!/files/.gitkeep +/img/curiga/ + +# Logs and temporary files +error_log +**/error_log +*.log +*.tmp +*.temp +tmp/ +temp/ +cache/ + +# Backups, archives, and exported bundles +*.zip +*.rar +*.7z +*.tar +*.tar.gz +*.tgz +*.bak +*.backup +*.old +bekap/ +backup/ +backups/ + +# Known unrelated/backup project folders +/direktori-spn/ +/pkm/ +/simpanghilir/ +/sisesta/ +/rekomendasi-artikel/ +/pedoman-old/ + +# OS/editor files +.DS_Store +Thumbs.db +desktop.ini +.idea/ +.vscode/ + +# Docker local data should be volumes, not Git content +docker-data/ +.docker-data/ diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..572620c --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,74 @@ +# SPOTA Docker + +Setup ini menjalankan aplikasi legacy SPOTA dengan PHP 7.4 Apache dan MySQL 8 dalam satu `docker-compose.yml`. + +## Jalankan Lokal + +```powershell +copy .env.example .env +docker compose up -d --build +``` + +Akses aplikasi: + +```text +http://localhost:8080 +http://localhost:8080/admin/login.php +http://localhost:8080/dosen/login.php +http://localhost:8080/mahasiswa/login.php +``` + +## Stop + +```powershell +docker compose down +``` + +## Reset Database + +Perintah ini menghapus volume DB dan import ulang dump dari `spota_db`. + +```powershell +docker compose down -v +docker compose up -d +``` + +## Database + +Dump diambil dari folder `spota_db` saat volume DB pertama kali dibuat. + +Database yang di-import: + +- `spota_spotadb` +- `spota_konsultasi` +- `spota_doxid` +- `spota_rek_artikel` + +## Volume/Data + +Folder berikut di-mount dari host supaya data upload tidak masuk image: + +- `./files:/var/www/html/files` +- `./img:/var/www/html/img` + +Opsional, upload berkas bisa dipindah ke lokasi di luar folder project dengan environment variable: + +- `FILES_STORAGE_PATH=/absolute/path/to/files` + +Jika `FILES_STORAGE_PATH` tidak diisi, aplikasi tetap memakai default `files/` di dalam document root. +Folder target akan dibuat otomatis saat upload pertama. +Jika path tersebut berada di luar `/var/www/html/files`, sesuaikan juga volume mount container ke lokasi yang sama. + +Untuk Coolify, jadikan path ini persistent storage. + +## Coolify + +Sesuaikan environment berikut di Coolify: + +- `APP_URL` +- `DB_USER` +- `DB_PASSWORD` +- `MYSQL_ROOT_PASSWORD` +- `PHP_DISPLAY_ERRORS=0` untuk production + +Port internal app adalah `80`. Database internal memakai service name `db` pada port `3306`. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1782bb8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM php:7.4-apache + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libonig-dev \ + libpng-dev \ + libzip-dev \ + unzip \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j"$(nproc)" pdo_mysql mysqli gd zip mbstring exif \ + && a2enmod rewrite headers \ + && rm -rf /var/lib/apt/lists/* + +COPY docker/php.ini /usr/local/etc/php/conf.d/spota.ini +COPY docker/apache-vhost.conf /etc/apache2/sites-available/000-default.conf + +WORKDIR /var/www/html +COPY . /var/www/html + +RUN mkdir -p /var/www/html/files /var/www/html/img /tmp/spota_sessions \ + && chown -R www-data:www-data /var/www/html/files /var/www/html/img /tmp/spota_sessions diff --git a/Dockerfile.coolify b/Dockerfile.coolify new file mode 100644 index 0000000..8a64e38 --- /dev/null +++ b/Dockerfile.coolify @@ -0,0 +1,31 @@ +FROM php:8.2-apache-bookworm + +RUN rm -rf /var/lib/apt/lists/* \ + && apt-get clean \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + libcurl4-openssl-dev \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libonig-dev \ + libpng-dev \ + libwebp-dev \ + libzip-dev \ + unzip \ + && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \ + && docker-php-ext-install -j"$(nproc)" pdo_mysql mysqli gd curl zip mbstring exif \ + && a2enmod rewrite headers \ + && printf 'ServerName localhost\n' > /etc/apache2/conf-available/server-name.conf \ + && a2enconf server-name \ + && rm -rf /var/lib/apt/lists/* + +COPY docker/php.ini /usr/local/etc/php/conf.d/spota.ini +COPY docker/apache-vhost.conf /etc/apache2/sites-available/000-default.conf + +WORKDIR /var/www/html +COPY . /var/www/html/ + +RUN mkdir -p /var/www/html/files /var/www/html/img /tmp/spota_sessions \ + && chown -R www-data:www-data /var/www/html /tmp/spota_sessions + +EXPOSE 80 diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml new file mode 100644 index 0000000..80582a0 --- /dev/null +++ b/docker-compose.coolify.yml @@ -0,0 +1,49 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile.coolify + restart: unless-stopped + environment: + APP_URL: ${APP_URL} + DB_HOST: db + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + DB_NAME: ${DB_NAME:-spota_spotadb} + DB_SPOTA: ${DB_SPOTA:-spota_spotadb} + DB_KONSULTASI: ${DB_KONSULTASI:-spota_konsultasi} + DB_BIO: ${DB_BIO:-spota_spotadb} + DB_DOSEN: ${DB_DOSEN:-spota_spotadb} + SERVICE_DB_NAME: ${SERVICE_DB_NAME:-spota_spotadb} + PHP_DISPLAY_ERRORS: ${PHP_DISPLAY_ERRORS:-0} + FILES_STORAGE_PATH: ${FILES_STORAGE_PATH:-/var/www/html/files} + volumes: + - spota_files:/var/www/html/files + - spota_img:/var/www/html/img + depends_on: + db: + condition: service_healthy + + db: + image: mysql:8.0 + restart: unless-stopped + command: --default-authentication-plugin=mysql_native_password --character-set-server=latin1 --collation-server=latin1_swedish_ci --sql-mode=NO_ENGINE_SUBSTITUTION + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASSWORD} + MYSQL_DATABASE: ${DB_NAME:-spota_spotadb} + volumes: + - spota_db_data:/var/lib/mysql + - ./docker/mysql-init:/docker-entrypoint-initdb.d:ro + - ./spota_db:/spota_db:ro + healthcheck: + test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$${MYSQL_ROOT_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 20 + +volumes: + spota_db_data: + spota_files: + spota_img: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e3c5016 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +services: + app: + build: . + container_name: spota-app + restart: unless-stopped + ports: + - "${APP_PORT:-8080}:80" + environment: + APP_URL: ${APP_URL:-http://localhost:8080} + DB_HOST: ${DB_HOST:-db} + DB_USER: ${DB_USER:-spota_user} + DB_PASSWORD: ${DB_PASSWORD:-spota_password} + DB_NAME: ${DB_NAME:-spota_spotadb} + DB_SPOTA: ${DB_SPOTA:-spota_spotadb} + DB_KONSULTASI: ${DB_KONSULTASI:-spota_konsultasi} + DB_BIO: ${DB_BIO:-spota_spotadb} + DB_DOSEN: ${DB_DOSEN:-spota_spotadb} + SERVICE_DB_NAME: ${SERVICE_DB_NAME:-spota_spotadb} + PHP_DISPLAY_ERRORS: ${PHP_DISPLAY_ERRORS:-1} + FILES_STORAGE_PATH: ${FILES_STORAGE_PATH:-/var/www/html/files} + volumes: + - ./files:/var/www/html/files + - ./img:/var/www/html/img + depends_on: + db: + condition: service_healthy + + db: + image: mysql:8.0 + container_name: spota-db + restart: unless-stopped + command: --default-authentication-plugin=mysql_native_password --character-set-server=latin1 --collation-server=latin1_swedish_ci + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root_password} + MYSQL_USER: ${DB_USER:-spota_user} + MYSQL_PASSWORD: ${DB_PASSWORD:-spota_password} + MYSQL_DATABASE: ${DB_NAME:-spota_spotadb} + ports: + - "${DB_PORT:-3307}:3306" + volumes: + - db_data:/var/lib/mysql + - ./docker/mysql-init:/docker-entrypoint-initdb.d:ro + - ./spota_db:/spota_db:ro + healthcheck: + test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$${MYSQL_ROOT_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 20 + +volumes: + db_data: diff --git a/docker/apache-vhost.conf b/docker/apache-vhost.conf new file mode 100644 index 0000000..868eed6 --- /dev/null +++ b/docker/apache-vhost.conf @@ -0,0 +1,13 @@ + + ServerName localhost + DocumentRoot /var/www/html + + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + diff --git a/docker/mysql-init/00-import-spota-databases.sh b/docker/mysql-init/00-import-spota-databases.sh new file mode 100644 index 0000000..7f532e1 --- /dev/null +++ b/docker/mysql-init/00-import-spota-databases.sh @@ -0,0 +1,33 @@ +#!/bin/sh +set -e + +mysql_exec() { + mysql -uroot -p"$MYSQL_ROOT_PASSWORD" "$@" +} + +import_database() { + db_name="$1" + create_file="$2" + data_file="$3" + + if [ -f "$create_file" ]; then + mysql_exec < "$create_file" + else + mysql_exec -e "CREATE DATABASE IF NOT EXISTS \`$db_name\`;" + fi + + if [ -f "$data_file" ]; then + mysql_exec "$db_name" < "$data_file" + fi +} + +import_database "spota_spotadb" "/spota_db/spota_spotadb.create" "/spota_db/spota_spotadb.sql" +import_database "spota_konsultasi" "/spota_db/spota_konsultasi.create" "/spota_db/spota_konsultasi.sql" +import_database "spota_doxid" "/spota_db/spota_doxid.create" "/spota_db/spota_doxid.sql" +import_database "spota_rek_artikel" "/spota_db/spota_rek_artikel.create" "/spota_db/spota_rek_artikel.sql" + +mysql_exec -e "GRANT ALL PRIVILEGES ON \`spota_spotadb\`.* TO '$MYSQL_USER'@'%';" +mysql_exec -e "GRANT ALL PRIVILEGES ON \`spota_konsultasi\`.* TO '$MYSQL_USER'@'%';" +mysql_exec -e "GRANT ALL PRIVILEGES ON \`spota_doxid\`.* TO '$MYSQL_USER'@'%';" +mysql_exec -e "GRANT ALL PRIVILEGES ON \`spota_rek_artikel\`.* TO '$MYSQL_USER'@'%';" +mysql_exec -e "FLUSH PRIVILEGES;" diff --git a/docker/php.ini b/docker/php.ini new file mode 100644 index 0000000..511b20d --- /dev/null +++ b/docker/php.ini @@ -0,0 +1,13 @@ +display_errors = ${PHP_DISPLAY_ERRORS} +log_errors = On +error_reporting = E_ALL +max_execution_time = 120 +max_input_time = 120 +max_input_vars = 5000 +memory_limit = 512M +post_max_size = 32M +upload_max_filesize = 32M +session.gc_maxlifetime = 604800 +session.save_path = "/tmp/spota_sessions" +allow_url_fopen = On +date.timezone = Asia/Jakarta