From 963a25a14fcea521302f1487713b82a537771cae Mon Sep 17 00:00:00 2001 From: Zaid Masri Date: Thu, 11 Dec 2025 18:46:32 -0500 Subject: [PATCH 1/7] feat(infra): init simple docker --- .gitignore | 2 ++ Dockerfile | 54 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 28 ++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index b5d2236a57..0d26bc266e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ var/* # Ignore node_modules folder node_modules + +.phpactor.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..3082f5bbdc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,54 @@ +FROM php:8.2-apache + +# 1. Install System Dependencies (Minimal required for Gibbon) +# TODO: Pin version in apt get install +RUN apt-get update && apt-get install -y \ + git \ + unzip \ + libicu-dev \ + libzip-dev \ + libpng-dev \ + libjpeg-dev \ + libfreetype6-dev \ + libxml2-dev \ + gettext \ + && rm -rf /var/lib/apt/lists/* + +# 2. Install PHP Extensions +RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j"$(nproc)" \ + mysqli \ + pdo_mysql \ + gd \ + zip \ + intl \ + xml \ + gettext \ + bcmath + +# Enable Apache mod_rewrite +RUN a2enmod rewrite + +# 3. Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +WORKDIR /var/www/html + +# 4. Clone Gibbon v31 (Latest Stable) +RUN git clone --depth 1 --branch v31.0.00 https://github.com/GibbonEdu/core.git . \ + && rm -rf .git + +# 5. Install PHP Dependencies +RUN composer install --no-dev --optimize-autoloader + +# 6. Configure PHP for Gibbon (Upload limits, etc.) +RUN echo "upload_max_filesize = 50M" > /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "post_max_size = 50M" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "max_input_vars = 5000" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/gibbon.ini + +# 7. Permissions (Crucial for the Web Installer to work) +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html + +CMD ["apache2-foreground"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..0847954039 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.8" + +services: + app: + build: . + container_name: gibbon_app + ports: + - "8080:80" + depends_on: + - db + restart: always + + db: + image: mysql:8.0 + container_name: gibbon_db + environment: + - MYSQL_DATABASE=gibbon + - MYSQL_USER=gibbon + - MYSQL_PASSWORD=gibbonpass + - MYSQL_ROOT_PASSWORD=rootpass + volumes: + - gibbon_db_data:/var/lib/mysql + # Native password plugin ensures PHP can connect easily + command: --default-authentication-plugin=mysql_native_password + restart: always + +volumes: + gibbon_db_data: From 886e936954b6f6cb52088c2e790c29c9db2ba312 Mon Sep 17 00:00:00 2001 From: Zaid Masri Date: Fri, 12 Dec 2025 00:42:16 -0500 Subject: [PATCH 2/7] refactor(docker): create a development and base docker compose file --- docker-compose.dev.yaml | 6 ++++++ docker-compose.yaml | 28 ++++++++++++++++++++++++++++ docker-compose.yml | 28 ---------------------------- 3 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 docker-compose.dev.yaml create mode 100644 docker-compose.yaml delete mode 100644 docker-compose.yml diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml new file mode 100644 index 0000000000..bcad5f2681 --- /dev/null +++ b/docker-compose.dev.yaml @@ -0,0 +1,6 @@ +version: "3.8" + +services: + app: + ports: + - "8080:80" diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000000..a101f66bcf --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,28 @@ +version: "3.8" + +services: + app: + build: . + container_name: gibbon_app + # ports: + # - "8080:80" + depends_on: + - db + restart: always + + db: + image: mysql:8.0 + container_name: gibbon_db + environment: + - MYSQL_DATABASE=${MYSQL_DATABASE:-gibbon} + - MYSQL_USER=${MYSQL_USER:-gibbon} + - MYSQL_PASSWORD=${MYSQL_PASSWORD:-gibbonpass} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-rootpass} + volumes: + - gibbon_db_data:/var/lib/mysql + # Native password plugin ensures PHP can connect easily + command: --default-authentication-plugin=mysql_native_password + restart: always + +volumes: + gibbon_db_data: diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 0847954039..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: "3.8" - -services: - app: - build: . - container_name: gibbon_app - ports: - - "8080:80" - depends_on: - - db - restart: always - - db: - image: mysql:8.0 - container_name: gibbon_db - environment: - - MYSQL_DATABASE=gibbon - - MYSQL_USER=gibbon - - MYSQL_PASSWORD=gibbonpass - - MYSQL_ROOT_PASSWORD=rootpass - volumes: - - gibbon_db_data:/var/lib/mysql - # Native password plugin ensures PHP can connect easily - command: --default-authentication-plugin=mysql_native_password - restart: always - -volumes: - gibbon_db_data: From d0e9fac4a19d49b17ac9e5a88b25e3b709c22558 Mon Sep 17 00:00:00 2001 From: Zaid Masri Date: Fri, 12 Dec 2025 01:46:20 -0500 Subject: [PATCH 3/7] refactor(docker): pass default env vars for DB --- docker-compose.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index a101f66bcf..895dd1f79d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,8 +4,6 @@ services: app: build: . container_name: gibbon_app - # ports: - # - "8080:80" depends_on: - db restart: always From fe42027b42596ef229c0d9863d0b6943eeaf2fc4 Mon Sep 17 00:00:00 2001 From: Ali Alam Date: Tue, 17 Mar 2026 10:53:06 +0800 Subject: [PATCH 4/7] Docker: added missing extensions, fix PHP ini values, AllowOverride, permissions and build setup --- .dockerignore | 25 +++++++++++++++++++++++++ Dockerfile | 40 ++++++++++++++++++++++++---------------- docker-compose.dev.yaml | 4 +--- docker-compose.yaml | 22 ++++++++++++++++------ 4 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..e018e63580 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +# Never bake local credentials or environment config into the image +config.php + +# Git history +.git +.gitignore + +# Local dev/test artifacts +/uploads/* +!/uploads/.htaccess +/var/* +!/var/.htaccess + +# Composer dev cache +vendor/ + +# Docker files themselves +Dockerfile +docker-compose*.yaml +.dockerignore + +# IDE and OS files +.DS_Store +*.code-workspace +.vscode/ diff --git a/Dockerfile b/Dockerfile index 3082f5bbdc..91058cac28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,7 @@ -FROM php:8.2-apache +FROM php:8.3-apache -# 1. Install System Dependencies (Minimal required for Gibbon) -# TODO: Pin version in apt get install +# 1. Install System Dependencies RUN apt-get update && apt-get install -y \ - git \ unzip \ libicu-dev \ libzip-dev \ @@ -11,6 +9,8 @@ RUN apt-get update && apt-get install -y \ libjpeg-dev \ libfreetype6-dev \ libxml2-dev \ + libcurl4-openssl-dev \ + libonig-dev \ gettext \ && rm -rf /var/lib/apt/lists/* @@ -24,31 +24,39 @@ RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ intl \ xml \ gettext \ - bcmath + bcmath \ + curl \ + mbstring # Enable Apache mod_rewrite -RUN a2enmod rewrite +RUN a2enmod rewrite \ + && sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf # 3. Install Composer -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html -# 4. Clone Gibbon v31 (Latest Stable) -RUN git clone --depth 1 --branch v31.0.00 https://github.com/GibbonEdu/core.git . \ - && rm -rf .git +# 4. Copy application source from local context +COPY . . # 5. Install PHP Dependencies RUN composer install --no-dev --optimize-autoloader -# 6. Configure PHP for Gibbon (Upload limits, etc.) +# 6. Configure PHP for Gibbon RUN echo "upload_max_filesize = 50M" > /usr/local/etc/php/conf.d/gibbon.ini \ && echo "post_max_size = 50M" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "max_input_vars = 5000" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/gibbon.ini + && echo "max_input_vars = 8000" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "max_file_uploads = 20" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "allow_url_fopen = On" >> /usr/local/etc/php/conf.d/gibbon.ini \ + && echo "session.gc_maxlifetime = 1200" >> /usr/local/etc/php/conf.d/gibbon.ini -# 7. Permissions (Crucial for the Web Installer to work) +# 7. Permissions RUN chown -R www-data:www-data /var/www/html \ - && chmod -R 755 /var/www/html + && find /var/www/html -type d -exec chmod 755 {} \; \ + && find /var/www/html -type f -exec chmod 644 {} \; -CMD ["apache2-foreground"] +EXPOSE 80 + +CMD ["apache2-foreground"] \ No newline at end of file diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index bcad5f2681..5a1cb3b2b4 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -1,6 +1,4 @@ -version: "3.8" - services: app: ports: - - "8080:80" + - "8888:80" diff --git a/docker-compose.yaml b/docker-compose.yaml index 895dd1f79d..fa48dd2de4 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,26 +1,36 @@ -version: "3.8" - services: app: build: . container_name: gibbon_app depends_on: - - db - restart: always + db: + condition: service_healthy + restart: unless-stopped db: image: mysql:8.0 container_name: gibbon_db + + # Gibbon Docker Environment Variables environment: + # MySQL database name (default: gibbon) - MYSQL_DATABASE=${MYSQL_DATABASE:-gibbon} + # MySQL application user credentials - MYSQL_USER=${MYSQL_USER:-gibbon} - MYSQL_PASSWORD=${MYSQL_PASSWORD:-gibbonpass} + # MySQL root password — keep this strong in production - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-rootpass} volumes: - gibbon_db_data:/var/lib/mysql # Native password plugin ensures PHP can connect easily command: --default-authentication-plugin=mysql_native_password - restart: always - + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpass}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + restart: unless-stopped + volumes: gibbon_db_data: From b58521cce03ae24709f9319e0fbc413eac9d0823 Mon Sep 17 00:00:00 2001 From: Ali Alam Date: Mon, 11 May 2026 15:31:14 +0800 Subject: [PATCH 5/7] Docker: Added improvements based suggestions from a community member --- .dockerignore | 4 ++ .env.example | 18 ++++++ .gitignore | 3 + docker-compose.dev.yaml | 4 -- Dockerfile => ops/Dockerfile | 19 +++---- ops/docker-compose.dev.yaml | 12 ++++ .../docker-compose.yaml | 20 +++++-- ops/php/gibbon.ini | 14 +++++ up.sh | 56 +++++++++++++++++++ 9 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 .env.example delete mode 100644 docker-compose.dev.yaml rename Dockerfile => ops/Dockerfile (63%) create mode 100644 ops/docker-compose.dev.yaml rename docker-compose.yaml => ops/docker-compose.yaml (60%) create mode 100644 ops/php/gibbon.ini create mode 100755 up.sh diff --git a/.dockerignore b/.dockerignore index e018e63580..b81c10430b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,6 @@ # Never bake local credentials or environment config into the image config.php +.env # Git history .git @@ -18,6 +19,9 @@ vendor/ Dockerfile docker-compose*.yaml .dockerignore +ops/docker-compose*.yaml +up.sh +.env.example # IDE and OS files .DS_Store diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..5901e9f2f5 --- /dev/null +++ b/.env.example @@ -0,0 +1,18 @@ +# ============================================================ +# Gibbon Docker Environment Configuration +# ============================================================ +# Copy this file to .env and adjust values before running: cp .env.example .env +# The .env file is automatically read by Docker Compose. +# ============================================================ + +## PHP version used to build the app image. Examples: 8.2, 8.3 +PHP_VERSION=8.3 + +## MySQL image version +MYSQL_VERSION=8.0 + +## Database credentials — change these before use +MYSQL_DATABASE=gibbon +MYSQL_USER=gibbon +MYSQL_PASSWORD=change_me +MYSQL_ROOT_PASSWORD=change_me diff --git a/.gitignore b/.gitignore index 0d26bc266e..c4507e3de0 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ var/* node_modules .phpactor.json + +# Docker environment — never commit real credentials +.env diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml deleted file mode 100644 index 5a1cb3b2b4..0000000000 --- a/docker-compose.dev.yaml +++ /dev/null @@ -1,4 +0,0 @@ -services: - app: - ports: - - "8888:80" diff --git a/Dockerfile b/ops/Dockerfile similarity index 63% rename from Dockerfile rename to ops/Dockerfile index 91058cac28..f3648e796f 100644 --- a/Dockerfile +++ b/ops/Dockerfile @@ -1,4 +1,6 @@ -FROM php:8.3-apache +# PHP_VERSION can be overridden at build time via --build-arg or docker-compose.yaml +ARG PHP_VERSION=8.3 +FROM php:${PHP_VERSION}-apache # 1. Install System Dependencies RUN apt-get update && apt-get install -y \ @@ -38,19 +40,16 @@ COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html # 4. Copy application source from local context +# Build context is the project root (see ops/docker-compose.yaml context: ..) COPY . . # 5. Install PHP Dependencies -RUN composer install --no-dev --optimize-autoloader +RUN composer install --no-dev --optimize-autoloader --no-interaction # 6. Configure PHP for Gibbon -RUN echo "upload_max_filesize = 50M" > /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "post_max_size = 50M" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "max_input_vars = 8000" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "max_file_uploads = 20" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "allow_url_fopen = On" >> /usr/local/etc/php/conf.d/gibbon.ini \ - && echo "session.gc_maxlifetime = 1200" >> /usr/local/etc/php/conf.d/gibbon.ini +# Path is relative to build context (project root), so ops/php/gibbon.ini +# In dev, this file is volume-mounted so changes take effect without a rebuild. +COPY ops/php/gibbon.ini /usr/local/etc/php/conf.d/gibbon.ini # 7. Permissions RUN chown -R www-data:www-data /var/www/html \ @@ -59,4 +58,4 @@ RUN chown -R www-data:www-data /var/www/html \ EXPOSE 80 -CMD ["apache2-foreground"] \ No newline at end of file +CMD ["apache2-foreground"] diff --git a/ops/docker-compose.dev.yaml b/ops/docker-compose.dev.yaml new file mode 100644 index 0000000000..db68f10c62 --- /dev/null +++ b/ops/docker-compose.dev.yaml @@ -0,0 +1,12 @@ +services: + app: + ports: + - "8888:80" + volumes: + ## Mount project root so live edits are immediately reflected without rebuilding the image. This overrides the COPY in the Dockerfile for local development. + - .:/var/www/html + ## Mount PHP config so values can be changed without an image rebuild. + - ./ops/php/gibbon.ini:/usr/local/etc/php/conf.d/gibbon.ini:ro + ## In dev, the volume mount hides vendor baked into the image. This command installs dependencies at startup if vendor/ is missing. + command: > + bash -c "[ ! -d vendor ] && composer install; apache2-foreground" diff --git a/docker-compose.yaml b/ops/docker-compose.yaml similarity index 60% rename from docker-compose.yaml rename to ops/docker-compose.yaml index fa48dd2de4..35b4ebba5d 100644 --- a/docker-compose.yaml +++ b/ops/docker-compose.yaml @@ -1,6 +1,14 @@ +name: gibbon + services: app: - build: . + build: + # Context is project root so COPY . . captures all source code + context: . + # Path to Dockerfile is relative to the build context (project root) + dockerfile: ops/Dockerfile + args: + PHP_VERSION: ${PHP_VERSION:-8.3} container_name: gibbon_app depends_on: db: @@ -8,7 +16,7 @@ services: restart: unless-stopped db: - image: mysql:8.0 + image: mysql:${MYSQL_VERSION:-8.0} container_name: gibbon_db # Gibbon Docker Environment Variables @@ -17,20 +25,20 @@ services: - MYSQL_DATABASE=${MYSQL_DATABASE:-gibbon} # MySQL application user credentials - MYSQL_USER=${MYSQL_USER:-gibbon} - - MYSQL_PASSWORD=${MYSQL_PASSWORD:-gibbonpass} + - MYSQL_PASSWORD=${MYSQL_PASSWORD:?MYSQL_PASSWORD is not set. Copy .env.example to .env and set a password.} # MySQL root password — keep this strong in production - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-rootpass} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD is not set. Copy .env.example to .env and set a password.} volumes: - gibbon_db_data:/var/lib/mysql # Native password plugin ensures PHP can connect easily command: --default-authentication-plugin=mysql_native_password healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpass}"] + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped - + volumes: gibbon_db_data: diff --git a/ops/php/gibbon.ini b/ops/php/gibbon.ini new file mode 100644 index 0000000000..43d27856db --- /dev/null +++ b/ops/php/gibbon.ini @@ -0,0 +1,14 @@ +; ============================================================ +; Gibbon PHP Configuration +; ============================================================ +; This file is mounted into the container at: /usr/local/etc/php/conf.d/gibbon.ini +; For development, edit values here and restart the container +; ============================================================ + +upload_max_filesize = 50M +post_max_size = 50M +max_input_vars = 8000 +memory_limit = 256M +max_file_uploads = 20 +allow_url_fopen = On +session.gc_maxlifetime = 1200 diff --git a/up.sh b/up.sh new file mode 100755 index 0000000000..c5645dd784 --- /dev/null +++ b/up.sh @@ -0,0 +1,56 @@ +#============================================================= +# Gibbon Local Development — Docker helper +# ============================================================= +# Usage: +# ./up.sh Start (or rebuild) the dev environment +# ./up.sh down Stop containers and remove volumes (resets DB) +# ./up.sh logs Tail live logs from all containers +# ============================================================= +set -euo pipefail + +## Ensure the script is always run from the project root +if [ ! -f "ops/docker-compose.yaml" ]; then + echo "Error: Run this script from the project root (where up.sh lives)." + exit 1 +fi + +## Ensure the local environment file exists +if [ ! -f ".env" ]; then + echo "Error: .env was not found. Create it first with: cp .env.example .env" + exit 1 +fi + +## Ensure Docker is installed and the daemon is running +if ! command -v docker >/dev/null 2>&1; then + echo "Error: Docker is not installed or not available on PATH." + exit 1 +fi + +if ! docker info >/dev/null 2>&1; then + echo "Error: Docker is not running. Start Docker Desktop and try again." + exit 1 +fi + +COMPOSE_FILES="--project-directory . -f ops/docker-compose.yaml -f ops/docker-compose.dev.yaml" + +case "${1:-up}" in + up) + echo "Starting Gibbon dev environment..." + docker compose $COMPOSE_FILES up -d --build + echo "" + echo "Gibbon is running at: http://localhost:8888" + echo "To follow logs: ./up.sh logs" + echo "To stop: ./up.sh down" + ;; + down) + echo "Stopping Gibbon dev environment and removing volumes..." + docker compose $COMPOSE_FILES down -v + ;; + logs) + docker compose $COMPOSE_FILES logs -f + ;; + *) + echo "Usage: $0 [up|down|logs]" + exit 1 + ;; +esac From 92882fdf9f58c91adf4cb2f3d2e8e888f0c4299a Mon Sep 17 00:00:00 2001 From: Ali Alam Date: Tue, 12 May 2026 10:12:22 +0800 Subject: [PATCH 6/7] Docker: This Docker setup allows developers to run a local development setup so contributors can run Gibbon without manually installing and configuring PHP, Apache, and MySQL on their machine. --- .dockerignore | 2 +- README.md | 35 ++++++++++++++++++++++++++++++++ .env.example => ops/.env-example | 3 ++- ops/docker-compose.dev.yaml | 2 +- ops/docker-compose.yaml | 4 ++-- up.sh | 12 ++++++++--- 6 files changed, 50 insertions(+), 8 deletions(-) rename .env.example => ops/.env-example (81%) diff --git a/.dockerignore b/.dockerignore index b81c10430b..c0057a53e0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -20,8 +20,8 @@ Dockerfile docker-compose*.yaml .dockerignore ops/docker-compose*.yaml +ops/.env-example up.sh -.env.example # IDE and OS files .DS_Store diff --git a/README.md b/README.md index b1c7f6ec4e..0b87e49414 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,41 @@ For installation instructions, visit [Getting Started: Installing Gibbon](https: For support visit [ask.gibbonedu.org](https://ask.gibbonedu.org) or see [our documentation](https://docs.gibbonedu.org). +## Docker Development Setup + +This Docker setup allows developers to run a local development setup so contributors can run Gibbon without manually installing and configuring PHP, Apache, and MySQL on their machine. + +## Prerequisites + +- Install [Docker Desktop](https://www.docker.com/products/docker-desktop) + +## Start The Development Environment + +From the project root, run: + +```bash +./up.sh +``` + +This script will: +- Check `.env` file exists and create it if not. +- Check that Docker Desktop is installed and running +- Build and start the Gibbon development server container + +Gibbon will be available at **http://localhost:8080** + +## Useful Commands + +Stop the development environment and remove volumes: +```bash +./up.sh down +``` + +View live container logs: +```bash +./up.sh logs +``` + ## Cutting Edge If you want to run the latest version of Gibbon, prerelease, you can get the source from our [GitHub repository](https://github.com/GibbonEdu/core). Remember, though, it is not stable, and you may lose data. This is not for the faint of heart. diff --git a/.env.example b/ops/.env-example similarity index 81% rename from .env.example rename to ops/.env-example index 5901e9f2f5..b75ce31133 100644 --- a/.env.example +++ b/ops/.env-example @@ -1,7 +1,8 @@ # ============================================================ # Gibbon Docker Environment Configuration # ============================================================ -# Copy this file to .env and adjust values before running: cp .env.example .env +# Copy this file to .env and adjust values before running. +# The up.sh helper will auto-create .env from this file if needed. # The .env file is automatically read by Docker Compose. # ============================================================ diff --git a/ops/docker-compose.dev.yaml b/ops/docker-compose.dev.yaml index db68f10c62..72b4d893f2 100644 --- a/ops/docker-compose.dev.yaml +++ b/ops/docker-compose.dev.yaml @@ -1,7 +1,7 @@ services: app: ports: - - "8888:80" + - "8080:80" volumes: ## Mount project root so live edits are immediately reflected without rebuilding the image. This overrides the COPY in the Dockerfile for local development. - .:/var/www/html diff --git a/ops/docker-compose.yaml b/ops/docker-compose.yaml index 35b4ebba5d..506cd424fb 100644 --- a/ops/docker-compose.yaml +++ b/ops/docker-compose.yaml @@ -25,9 +25,9 @@ services: - MYSQL_DATABASE=${MYSQL_DATABASE:-gibbon} # MySQL application user credentials - MYSQL_USER=${MYSQL_USER:-gibbon} - - MYSQL_PASSWORD=${MYSQL_PASSWORD:?MYSQL_PASSWORD is not set. Copy .env.example to .env and set a password.} + - MYSQL_PASSWORD=${MYSQL_PASSWORD:?MYSQL_PASSWORD is not set. Create .env from ops/.env-example and set a password.} # MySQL root password — keep this strong in production - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD is not set. Copy .env.example to .env and set a password.} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD is not set. Create .env from ops/.env-example and set a password.} volumes: - gibbon_db_data:/var/lib/mysql # Native password plugin ensures PHP can connect easily diff --git a/up.sh b/up.sh index c5645dd784..0a041227e7 100755 --- a/up.sh +++ b/up.sh @@ -16,8 +16,14 @@ fi ## Ensure the local environment file exists if [ ! -f ".env" ]; then - echo "Error: .env was not found. Create it first with: cp .env.example .env" - exit 1 + if [ ! -f "ops/.env-example" ]; then + echo "Error: .env was not found and ops/.env-example is missing." + exit 1 + fi + + cp ops/.env-example .env + echo "Created .env from ops/.env-example" + echo "Review .env to customize local settings if needed." fi ## Ensure Docker is installed and the daemon is running @@ -38,7 +44,7 @@ case "${1:-up}" in echo "Starting Gibbon dev environment..." docker compose $COMPOSE_FILES up -d --build echo "" - echo "Gibbon is running at: http://localhost:8888" + echo "Gibbon is running at: http://localhost:8080" echo "To follow logs: ./up.sh logs" echo "To stop: ./up.sh down" ;; From f9deb55daed5790cabdb5fdad372f8b18a6f907c Mon Sep 17 00:00:00 2001 From: Ali Alam Date: Tue, 16 Jun 2026 10:22:46 +0800 Subject: [PATCH 7/7] Docker: Added some code improvements after suggestions from code reviewer --- ops/.env-example | 3 +++ ops/Dockerfile | 32 ++++++++++++++++---------------- ops/docker-compose.dev.yaml | 5 +---- up.sh | 14 ++++++-------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/ops/.env-example b/ops/.env-example index b75ce31133..d46ac04b80 100644 --- a/ops/.env-example +++ b/ops/.env-example @@ -17,3 +17,6 @@ MYSQL_DATABASE=gibbon MYSQL_USER=gibbon MYSQL_PASSWORD=change_me MYSQL_ROOT_PASSWORD=change_me + +## Docker Compose file selection — lets you run `docker compose` commands +COMPOSE_FILE=ops/docker-compose.yaml:ops/docker-compose.dev.yaml diff --git a/ops/Dockerfile b/ops/Dockerfile index f3648e796f..74b356a139 100644 --- a/ops/Dockerfile +++ b/ops/Dockerfile @@ -39,22 +39,22 @@ COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html -# 4. Copy application source from local context -# Build context is the project root (see ops/docker-compose.yaml context: ..) -COPY . . - -# 5. Install PHP Dependencies -RUN composer install --no-dev --optimize-autoloader --no-interaction - -# 6. Configure PHP for Gibbon -# Path is relative to build context (project root), so ops/php/gibbon.ini -# In dev, this file is volume-mounted so changes take effect without a rebuild. -COPY ops/php/gibbon.ini /usr/local/etc/php/conf.d/gibbon.ini - -# 7. Permissions -RUN chown -R www-data:www-data /var/www/html \ - && find /var/www/html -type d -exec chmod 755 {} \; \ - && find /var/www/html -type f -exec chmod 644 {} \; +# Steps 4–7 are intentionally commented out for the dev environment. + +# # 4. Copy application source from local context +# COPY . . + +# # 5. Install PHP Dependencies +# RUN composer install --no-dev --optimize-autoloader --no-interaction + +# # 6. Configure PHP for Gibbon +# # Path is relative to build context (project root), so ops/php/gibbon.ini +# COPY ops/php/gibbon.ini /usr/local/etc/php/conf.d/gibbon.ini + +# # 7. Permissions +# RUN chown -R www-data:www-data /var/www/html \ +# && find /var/www/html -not -path "*/vendor/*" -type d -exec chmod 755 {} + \ +# && find /var/www/html -not -path "*/vendor/*" -type f -exec chmod 644 {} + EXPOSE 80 diff --git a/ops/docker-compose.dev.yaml b/ops/docker-compose.dev.yaml index 72b4d893f2..579bb0473c 100644 --- a/ops/docker-compose.dev.yaml +++ b/ops/docker-compose.dev.yaml @@ -3,10 +3,7 @@ services: ports: - "8080:80" volumes: - ## Mount project root so live edits are immediately reflected without rebuilding the image. This overrides the COPY in the Dockerfile for local development. + ## Mount project root so live edits are immediately reflected without rebuilding the image. - .:/var/www/html ## Mount PHP config so values can be changed without an image rebuild. - ./ops/php/gibbon.ini:/usr/local/etc/php/conf.d/gibbon.ini:ro - ## In dev, the volume mount hides vendor baked into the image. This command installs dependencies at startup if vendor/ is missing. - command: > - bash -c "[ ! -d vendor ] && composer install; apache2-foreground" diff --git a/up.sh b/up.sh index 0a041227e7..d634600360 100755 --- a/up.sh +++ b/up.sh @@ -37,23 +37,21 @@ if ! docker info >/dev/null 2>&1; then exit 1 fi -COMPOSE_FILES="--project-directory . -f ops/docker-compose.yaml -f ops/docker-compose.dev.yaml" +DOCKER_COMPOSE="docker compose --project-directory ." case "${1:-up}" in up) echo "Starting Gibbon dev environment..." - docker compose $COMPOSE_FILES up -d --build + ${DOCKER_COMPOSE} build app db + ${DOCKER_COMPOSE} up -d + echo "Installing Composer dependencies (this may take a minute on first run)..." + ${DOCKER_COMPOSE} exec -T app composer install echo "" echo "Gibbon is running at: http://localhost:8080" echo "To follow logs: ./up.sh logs" - echo "To stop: ./up.sh down" - ;; - down) - echo "Stopping Gibbon dev environment and removing volumes..." - docker compose $COMPOSE_FILES down -v ;; logs) - docker compose $COMPOSE_FILES logs -f + docker compose logs -f ;; *) echo "Usage: $0 [up|down|logs]"