Add Docker Compose setup for local runs
PHP 8.3 + Apache image serving public/ on port 8080, with pdo_sqlite and mbstring built in. The container entrypoint applies migrations as www-data before starting Apache; the SQLite database and generated JWT signing key persist in a named "storage" volume. `docker compose up -d` is now the primary way to run the project without a local PHP toolchain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.dockerignore
|
||||||
|
vendor
|
||||||
|
storage
|
||||||
|
.env
|
||||||
|
.phpunit.cache
|
||||||
|
.phpunit.result.cache
|
||||||
|
docs
|
||||||
|
README.md
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM php:8.3-apache
|
||||||
|
|
||||||
|
# --- PHP extensions and CLI tools ----------------------------------------------
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libonig-dev \
|
||||||
|
unzip \
|
||||||
|
curl \
|
||||||
|
&& docker-php-ext-install pdo_sqlite mbstring \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# --- Composer ----------------------------------------------------------------
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
# --- Apache: document root -> public/, allow .htaccess rewrites -------------
|
||||||
|
RUN a2enmod rewrite
|
||||||
|
COPY docker/apache.conf /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
|
# --- PHP dependencies (own layer, cached unless composer.* changes) --------
|
||||||
|
COPY composer.json composer.lock ./
|
||||||
|
RUN composer install --no-dev --no-interaction --no-progress --prefer-dist --no-autoloader
|
||||||
|
|
||||||
|
# --- Application source ----------------------------------------------------
|
||||||
|
COPY . .
|
||||||
|
RUN composer dump-autoload --optimize --no-dev \
|
||||||
|
&& mkdir -p storage \
|
||||||
|
&& chown -R www-data:www-data storage
|
||||||
|
|
||||||
|
# --- Entrypoint: migrate, then hand off to Apache ------------------------
|
||||||
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
CMD ["apache2-foreground"]
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
|
||||||
|
CMD curl -fsS http://localhost/api/health || exit 1
|
||||||
@@ -11,18 +11,35 @@ SQLite file, plus a single-page frontend (added in a later stage).
|
|||||||
| 2 | Todo CRUD API | planned |
|
| 2 | Todo CRUD API | planned |
|
||||||
| 3 | Single-page frontend | planned |
|
| 3 | Single-page frontend | planned |
|
||||||
|
|
||||||
## Requirements
|
## Run with Docker
|
||||||
|
|
||||||
- PHP 8.1+ with the `pdo_sqlite` and `mbstring` extensions
|
The only requirement is Docker with the Compose plugin.
|
||||||
- [Composer](https://getcomposer.org/)
|
|
||||||
|
|
||||||
On Fedora:
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
This builds a PHP 8.3 + Apache image, applies migrations, and serves the API at
|
||||||
|
<http://localhost:8080> (e.g. `curl http://localhost:8080/api/health`).
|
||||||
|
|
||||||
|
- The SQLite database and the generated JWT signing key live in the `storage`
|
||||||
|
named volume, so they survive `docker compose restart` / `down` + `up`.
|
||||||
|
- After changing PHP source or `composer.json`, rebuild: `docker compose up -d --build`.
|
||||||
|
- `docker compose down -v` removes the volume and gives you a clean database.
|
||||||
|
- Override settings via the environment or a `.env` file in this directory
|
||||||
|
(Compose substitutes `APP_DEBUG`, `JWT_SECRET`, `JWT_TTL` — see
|
||||||
|
[docker-compose.yml](docker-compose.yml)).
|
||||||
|
|
||||||
|
## Run without Docker
|
||||||
|
|
||||||
|
Requires PHP 8.1+ with the `pdo_sqlite` and `mbstring` extensions, plus
|
||||||
|
[Composer](https://getcomposer.org/). On Fedora:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dnf install php-cli php-pdo php-mbstring composer
|
sudo dnf install php-cli php-pdo php-mbstring composer
|
||||||
```
|
```
|
||||||
|
|
||||||
## Setup
|
### Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer install
|
composer install
|
||||||
@@ -30,7 +47,7 @@ cp .env.example .env # optional; sane defaults are used without it
|
|||||||
composer migrate # creates storage/database.sqlite and its tables
|
composer migrate # creates storage/database.sqlite and its tables
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running
|
### Running
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer serve # http://localhost:8080 (php -S localhost:8080 -t public)
|
composer serve # http://localhost:8080 (php -S localhost:8080 -t public)
|
||||||
@@ -154,6 +171,9 @@ src/Http/JsonErrorHandler.php Uniform JSON error envelope
|
|||||||
src/Http/Controllers/ Request handlers
|
src/Http/Controllers/ Request handlers
|
||||||
src/Repository/ Database access
|
src/Repository/ Database access
|
||||||
migrations/*.sql Schema, applied by bin/migrate.php
|
migrations/*.sql Schema, applied by bin/migrate.php
|
||||||
|
Dockerfile PHP 8.3 + Apache image
|
||||||
|
docker-compose.yml One-command local stack
|
||||||
|
docker/ Apache vhost + container entrypoint
|
||||||
```
|
```
|
||||||
|
|
||||||
## Provenance
|
## Provenance
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
image: php-todo-list
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
environment:
|
||||||
|
APP_DEBUG: "${APP_DEBUG:-false}"
|
||||||
|
# Leave blank to auto-generate a secret into the storage volume on first run.
|
||||||
|
JWT_SECRET: "${JWT_SECRET:-}"
|
||||||
|
JWT_TTL: "${JWT_TTL:-86400}"
|
||||||
|
volumes:
|
||||||
|
# Persists the SQLite database and the generated signing key across restarts.
|
||||||
|
- storage:/var/www/html/storage
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
storage:
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<VirtualHost *:80>
|
||||||
|
DocumentRoot /var/www/html/public
|
||||||
|
|
||||||
|
<Directory /var/www/html/public>
|
||||||
|
Options -Indexes +FollowSymLinks
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
DirectoryIndex index.php
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||||
|
</VirtualHost>
|
||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# The storage directory may be a freshly created named volume; make sure it
|
||||||
|
# exists and is writable by the web-server user.
|
||||||
|
mkdir -p storage
|
||||||
|
chown -R www-data:www-data storage
|
||||||
|
|
||||||
|
# Apply pending migrations as www-data so the SQLite file it creates stays
|
||||||
|
# writable by Apache.
|
||||||
|
su -s /bin/sh -c 'php bin/migrate.php' www-data
|
||||||
|
|
||||||
|
exec docker-php-entrypoint "$@"
|
||||||
Reference in New Issue
Block a user