diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8c9ff1e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1 + +FROM php:8.2-apache + +WORKDIR /var/www/html + +# Install Composer by copying its binary from the official composer image +COPY --from=composer:lts /usr/bin/composer /usr/bin/composer + +# Copy dependency manifests first so Docker can cache this layer +# (only re-runs composer install if these files change) +COPY composer.json composer.lock ./ + +# Install PHP dependencies (production only, no dev packages) +RUN composer install --no-dev --no-interaction --optimize-autoloader + +# Use production php.ini defaults +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" + +# Copy the rest of the application source +COPY ./src /var/www/html + +# Make sure the web server user owns the files +RUN chown -R www-data:www-data /var/www/html + +USER www-data diff --git a/README.md b/README.md index 83d84f8..5d045e8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,104 @@ -# docker-php-sample +# Docker PHP Sample -A simple PHP web application example for [Docker's PHP Language Guide](https://docs.docker.com/language/php/). \ No newline at end of file +A simple PHP application containerized with Docker, using the official +`php:8.2-apache` image. Dependencies are managed with Composer. + +## Project structure + +``` +docker-php-sample/ +├── Dockerfile # Single-stage build: PHP 8.2 + Apache + Composer deps +├── composer.json # PHP dependency manifest +├── composer.lock # Locked dependency versions +├── src/ # Application source code (web root) +├── tests/ # Test suite +└── README.md +``` + +## Prerequisites + +- [Docker](https://docs.docker.com/get-docker/) installed and running +- Your user added to the `docker` group (or use `sudo` for Docker commands) + ```bash + sudo usermod -aG docker $USER + newgrp docker + ``` + +## Build the image + +From the project root: + +```bash +docker build -t php-app:latest . +``` + +This will: +1. Start from the `php:8.2-apache` base image +2. Copy the Composer binary in from the official `composer` image +3. Install PHP dependencies via `composer install` +4. Switch to production `php.ini` defaults +5. Copy in the application source from `src/` +6. Run the container as the non-root `www-data` user + +## Run the container + +```bash +docker run -d -p 9000:80 php-app:latest +``` + +- `-d` runs the container in the background (detached) +- `-p 9000:80` maps port `9000` on your host to port `80` inside the container + +Check it's running: + +```bash +docker ps +``` + +You should see something like: + +``` +PORTS +0.0.0.0:9000->80/tcp +``` + +## Access the app + +Open in your browser: + +``` +http://localhost:9000/hello.php +``` + +Or, if running on a remote server (e.g. EC2), replace `localhost` with the +server's public IP, and make sure port `9000` is allowed in your firewall / +security group inbound rules. + +## Stopping the container + +```bash +docker ps # find the container ID or name +docker stop # stop it +docker rm # remove it (optional) +``` + +## Rebuilding after code changes + +Any time you change `src/`, `composer.json`, or the `Dockerfile` itself, +rebuild the image and restart the container: + +```bash +docker build -t php-app:latest . +docker stop && docker rm +docker run -d -p 9000:80 php-app:latest +``` + +## Notes + +- This Dockerfile is **single-stage** (no multi-stage build), so the final + image includes Composer and its cache — larger than a multi-stage build, + but simpler to read and doesn't require BuildKit. +- If you see `the --mount option requires BuildKit`, that means a + Dockerfile is using BuildKit-only syntax (`RUN --mount=...`). Either + enable BuildKit (`DOCKER_BUILDKIT=1 docker build ...`) or use the + single-stage Dockerfile in this repo, which avoids that syntax entirely. diff --git a/src/database.php b/src/database.php deleted file mode 100644 index 88a2692..0000000 --- a/src/database.php +++ /dev/null @@ -1,47 +0,0 @@ -exec(" - CREATE TABLE IF NOT EXISTS messages ( - id INT AUTO_INCREMENT PRIMARY KEY, - message VARCHAR(255) NOT NULL - ) -"); - -// Create message -$stmt = $db_handle->query("SELECT COUNT(*) as count FROM messages"); -$row = $stmt->fetch(PDO::FETCH_ASSOC); -$count = $row['count']; -$db_handle->exec(" - INSERT INTO messages (message) - SELECT CONCAT('message-', '$count') - WHERE NOT EXISTS ( - SELECT 1 FROM messages WHERE message = CONCAT('message-', '$count') - ) -"); - -// Retrieve all records from the "messages" table -$stmt = $db_handle->query("SELECT * FROM messages"); - -// Print all records -while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - echo $row['id'] . " " . $row['message'] . "
"; -} - -// Close the database connection -$db_handle = null; -?>