diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..c0057a53e0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,29 @@ +# Never bake local credentials or environment config into the image +config.php +.env + +# 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 +ops/docker-compose*.yaml +ops/.env-example +up.sh + +# IDE and OS files +.DS_Store +*.code-workspace +.vscode/ diff --git a/.gitignore b/.gitignore index b5d2236a57..c4507e3de0 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,8 @@ var/* # Ignore node_modules folder node_modules + +.phpactor.json + +# Docker environment — never commit real credentials +.env 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/ops/.env-example b/ops/.env-example new file mode 100644 index 0000000000..d46ac04b80 --- /dev/null +++ b/ops/.env-example @@ -0,0 +1,22 @@ +# ============================================================ +# Gibbon Docker Environment Configuration +# ============================================================ +# 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. +# ============================================================ + +## 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 + +## 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 new file mode 100644 index 0000000000..74b356a139 --- /dev/null +++ b/ops/Dockerfile @@ -0,0 +1,61 @@ +# 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 \ + unzip \ + libicu-dev \ + libzip-dev \ + libpng-dev \ + libjpeg-dev \ + libfreetype6-dev \ + libxml2-dev \ + libcurl4-openssl-dev \ + libonig-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 \ + curl \ + mbstring + +# Enable Apache mod_rewrite +RUN a2enmod rewrite \ + && sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf + +# 3. Install Composer +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +WORKDIR /var/www/html + +# 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 + +CMD ["apache2-foreground"] diff --git a/ops/docker-compose.dev.yaml b/ops/docker-compose.dev.yaml new file mode 100644 index 0000000000..579bb0473c --- /dev/null +++ b/ops/docker-compose.dev.yaml @@ -0,0 +1,9 @@ +services: + app: + ports: + - "8080:80" + volumes: + ## 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 diff --git a/ops/docker-compose.yaml b/ops/docker-compose.yaml new file mode 100644 index 0000000000..506cd424fb --- /dev/null +++ b/ops/docker-compose.yaml @@ -0,0 +1,44 @@ +name: gibbon + +services: + app: + 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: + condition: service_healthy + restart: unless-stopped + + db: + image: mysql:${MYSQL_VERSION:-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:?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. 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 + command: --default-authentication-plugin=mysql_native_password + healthcheck: + 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..d634600360 --- /dev/null +++ b/up.sh @@ -0,0 +1,60 @@ +#============================================================= +# 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 + 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 +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 + +DOCKER_COMPOSE="docker compose --project-directory ." + +case "${1:-up}" in + up) + echo "Starting Gibbon dev environment..." + ${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" + ;; + logs) + docker compose logs -f + ;; + *) + echo "Usage: $0 [up|down|logs]" + exit 1 + ;; +esac