# PRD — indawo_docker

Evidence date: 2026-10-12. Source: `git@bitbucket.org:overdrive/indawo_docker.git`, `main` at `76c21e3` (2025-03-08, "updating container").

There is no prior PRD in Silicon Ark. The current README describes an upstream LAMP stack (`sprintcube/docker-compose-lamp`). The February commits on the same branch described a PHP 5.6 and MySQL 5.7 environment for a database named `indawo`. Requirements below come from the current tree unless a requirement is explicitly marked as historical.

This repository does not contain the Indawo application. It contains the containers a developer would start around an application that lives on the host.

## Product purpose

A developer can start a local web server, a MySQL 5.7 database, phpMyAdmin, and Redis, with the web container built from PHP 5.6 and Apache.

Provenance: **Implemented** (`docker-compose.yml`, `sample.env`, `bin/php56/Dockerfile`, `bin/mysql57/Dockerfile`).

The README states the stack is for local development and should not be used unmodified in production. Provenance: **Documented**.

The README also states that several PHP versions (5.4 through 8.3) and several database flavours are available by changing `PHPVERSION` and `DATABASE`. Those image directories are not in this tree. Only `bin/php56` and `bin/mysql57` exist. Provenance of the claim: **Documented**. Provenance of the directories: **Implemented** absence. Treating the README list as available in this checkout would be wrong.

## Users

No login, role, or permission model is implemented in this repository. The people described by the README are developers running Docker locally. Provenance: **Documented** (installation and contributing sections). **Inferred** from the absence of application code.

phpMyAdmin is configured with user `root` and the MySQL root password. Provenance: **Implemented** (`docker-compose.yml` `PMA_USER` / `PMA_PASSWORD`).

The README publishes phpMyAdmin at `http://localhost:8080/` with username `root` and password `tiger`. That password matches `MYSQL_ROOT_PASSWORD=tiger` in `sample.env`. Provenance: **Documented** and **Implemented**.

## Main workflows

### W1 — Configure and start the stack

Trigger: a developer follows the README installation.

1. Copy `sample.env` to `.env`. `.env` is gitignored.
2. Change values as needed. `sample.env` already sets `PHPVERSION=php56` and `DATABASE=mysql57`.
3. Run `docker compose up -d`.
4. Open `http://localhost`.

Provenance: **Documented** (`README.md`). The compose file requires those variables for image context and published ports. Provenance: **Implemented**.

The README's clone command is `git clone https://github.com/sprintcube/docker-compose-lamp.git`. This remote is `git@bitbucket.org:overdrive/indawo_docker.git`. Provenance: **Documented** mismatch with the remote.

`sample.env` sets `APACHE_LOG_DIR`. The compose file reads `LOG_DIR` and defaults it to `./logs/apache2`, which is the same path `APACHE_LOG_DIR` uses. The names differ. Provenance: **Implemented**.

### W2 — Serve a PHP application

Trigger: compose starts `webserver`.

- Build context is `./bin/${PHPVERSION}`. With `sample.env`, that is `bin/php56`, which uses `Dockerfile` (not `Dockerfile2`).
- Host port `${HOST_MACHINE_UNSECURE_HOST_PORT}` maps to container port 80. Default in `sample.env` is 80.
- Host port `${HOST_MACHINE_SECURE_HOST_PORT}` maps to container port 443. Default is 443.
- `${DOCUMENT_ROOT-./www}` is mounted read-write at `/var/www/html`.
- Apache `APACHE_DOCUMENT_ROOT` defaults to `/var/www/html`.
- Virtual hosts mount from `${VHOSTS_DIR-./config/vhosts}` onto `/etc/apache2/sites-enabled`.
- SSL files mount from `${SSL_DIR-./config/ssl}` onto `/etc/apache2/ssl/`.
- The container restarts with policy `always`.
- `links: database` is set. The database service name is `database`.

Provenance: **Implemented** (`docker-compose.yml`, `sample.env`).

`bin/php56/Dockerfile` writes `<?php phpinfo();` to `/var/www/html/index.php` inside the image. A bind mount of `./www` onto that path hides image files in that directory when the mount is applied. Whether a developer then sees phpinfo or their own `www` contents depends on the host directory. Provenance of the `phpinfo` file: **Implemented**. Provenance of the hide behaviour: **Inferred** from Docker bind-mount semantics. It was not run during this onboarding.

A volume entry is the string `-./filesystem:/var/www/filesystem`. Provenance: **Implemented** as written in `docker-compose.yml`. A host path of `-./filesystem` is **Inferred** to be a typo. It was not executed.

A second PHP ini mount uses the variable name `FileSyem` (spelled that way) and defaults to `./config/php/php.ini`, the same default as `PHP_INI`, and the same container path `/usr/local/etc/php/php.ini`. Provenance: **Implemented**.

### W3 — Store MySQL data

Trigger: compose starts `database`.

- Build context is `./bin/${DATABASE}`. With `sample.env`, that is `bin/mysql57`, whose Dockerfile is `FROM mysql:5.7`.
- Port publish is `127.0.0.1:${HOST_MACHINE_MYSQL_PORT}:3306`. Default host port is 3306. The bind address is localhost only.
- Environment passes `MYSQL_ROOT_PASSWORD`, `MYSQL_DATABASE`, `MYSQL_USER`, and `MYSQL_PASSWORD`.
- Uncommented `sample.env` values are root password `tiger`, database `docker`, user `docker`, password `docker`.
- Init scripts mount from `${MYSQL_INITDB_DIR-./config/initdb}` to `/docker-entrypoint-initdb.d`.
- Data directory mounts from `${MYSQL_DATA_DIR-./data/mysql}` to `/var/lib/mysql`.
- Restart policy is `always`.

Provenance: **Implemented**.

`sample.env` comments say PHP versions `<= 7.4` do not support MySQL 8 because of PDO. Provenance: **Documented**. This checkout's PHP image is 5.6 and its database image is 5.7, which matches that note. A MySQL 8 Dockerfile is not in the tree.

A commented block in `sample.env` sets user `silicon` and database `indawo_online`. It also contains a password. That password is not repeated here. Those three lines are comments, so Compose does not apply them. Provenance: **Documented**. Whether they are real credentials for a shared database is **Unknown / Requires Confirmation**.

The February compose file set database name `indawo`, user `user`, and plaintext development passwords, and stored data in a named volume `mysql_data`. That file was replaced in `76c21e3`. Provenance: **Implemented** in `cc17467` and `2567dfc`, **Removed** on `main`.

### W4 — Open phpMyAdmin

Trigger: compose starts `phpmyadmin`.

- Image is `phpmyadmin` with no tag.
- `PMA_HOST` is `database`, `PMA_PORT` is `3306`, `PMA_USER` is `root`, `PMA_PASSWORD` is `${MYSQL_ROOT_PASSWORD}`.
- Host ports: `${HOST_MACHINE_PMA_PORT}:80` and `${HOST_MACHINE_PMA_SECURE_PORT}:443`. Defaults in `sample.env` are 8080 and 8443. These publishes are not bound to `127.0.0.1`.
- `UPLOAD_LIMIT` and `MEMORY_LIMIT` default to `512M` in `sample.env`.
- An anonymous volume is mounted at `/sessions`.
- The host `php.ini` is also mounted at `/usr/local/etc/php/conf.d/php-phpmyadmin.ini`.

Provenance: **Implemented**. The README's port 8080, user `root`, and password `tiger` match the sample file. Provenance: **Documented**.

### W5 — Use Redis

Trigger: compose starts `redis`.

- Image is `redis:latest`.
- Port publish is `127.0.0.1:${HOST_MACHINE_REDIS_PORT}:6379`. Default host port is 6379.
- No volume, no password, and no custom Redis configuration are set.

Provenance: **Implemented**. The README says Redis runs on port 6379. Provenance: **Documented**.

No PHP Redis extension is installed in either Dockerfile. Provenance: **Implemented** absence. A PHP application in `www` cannot use `ext-redis` from this image unless it is added later. That limitation is **Inferred** from the extension list.

### W6 — Shell into the web container

The README says to run `docker compose exec webserver bash`. Provenance: **Documented**. The service name in the current compose file is `webserver`. Provenance: **Implemented**. The February service name was `php`. Provenance: **Removed**.

### W7 — Debug with Xdebug

- Both Dockerfiles install `xdebug-2.5.5` and append `xdebug.remote_enable=1` to `/usr/local/etc/php/php.ini`.
- Compose sets `XDEBUG_CONFIG` to `client_host=host.docker.internal remote_port=${XDEBUG_PORT}` and adds host `host.docker.internal:host-gateway`.
- `sample.env` sets `XDEBUG_PORT=9003` and leaves `9000` commented.

Provenance: **Implemented**.

The README says PHP `<= 7.3` uses Xdebug 2 and port 9000 in its example, and PHP `>= 7.4` uses Xdebug 3 and port 9003. This image is PHP 5.6 with Xdebug 2.5.5, while `sample.env` selects port 9003. Provenance of the README rule: **Documented**. Provenance of the port clash: **Inferred** from those two files. It was not executed.

The README's `php.ini` Xdebug snippet is not committed. `config/php/php.ini` is covered by `.gitignore` (`/config/*`). Provenance: **Documented** path, **not in git**.

### W8 — HTTPS

The README describes three ways to enable HTTPS with mkcert certificates placed in `config/ssl`, and by uncommenting a port-443 vhost in `config/vhosts/default.conf`. Provenance: **Documented**.

The PHP image creates `/etc/apache2/ssl` and runs `a2enmod ssl`. Provenance: **Implemented**.

`config/vhosts/default.conf` and `config/ssl` are not committed. Provenance: **not in git**. Whether HTTPS works with this image alone is **Unknown / Requires Confirmation**.

### W9 — Build-matrix check (Linux script)

Trigger: `dev_build_container.sh -b <php version>` on Linux.

The script refuses to run when `uname` is not `Linux`. It requires `docker`, `docker-compose`, `curl`, and `sed`. It deletes `./data/mysql/*`, writes env files under `./buildtest/`, runs `docker-compose --env-file ... up -d --build`, waits 30 seconds, and curls `http://localhost/test_db.php` and `http://localhost/test_db_pdo.php` looking for the string `proper`.

Provenance: **Implemented** (`dev_build_container.sh`). The usage text says the script removes all data in `data/mysql/*`. Provenance: **Documented** in that script.

The script's `sed` replacements look for `PHPVERSION=php8` and `DATABASE=mysql8`. `sample.env` contains `PHPVERSION=php56` and `DATABASE=mysql57`, so those substitutions do not match this sample file. Provenance: **Implemented** mismatch. **Inferred** result: the matrix would keep `php56` and `mysql57` from the copied sample. It was not executed.

`test_db.php` and `test_db_pdo.php` are not in git. Provenance: **not in git**.

## Functional requirements

### FR-001 — Local web and database stack

The system starts four services: a PHP Apache web server, MySQL, phpMyAdmin, and Redis.

- Actor: a developer with Docker.
- Trigger: `docker compose up -d` with an `.env` based on `sample.env`.
- Inputs: the variables listed in `sample.env`.
- Behaviour: containers are named `${COMPOSE_PROJECT_NAME}-${PHPVERSION}`, `${COMPOSE_PROJECT_NAME}-${DATABASE}`, `${COMPOSE_PROJECT_NAME}-phpmyadmin`, and `${COMPOSE_PROJECT_NAME}-redis`. With the sample file those names are `lamp-php56`, `lamp-mysql57`, `lamp-phpmyadmin`, and `lamp-redis`.
- Output: published ports as in W2–W5.
- Validation: Compose interpolation fails if required variables are empty. The file does not add a healthcheck.
- Error behaviour: **Unknown / Requires Confirmation** at runtime. No run was performed for this PRD.

Evidence: `docker-compose.yml`, `sample.env`. Implementation: **Implemented**. Confidence: High for the file contents. Runtime success was not observed.

### FR-002 — PHP 5.6 image with data extensions

The web image is PHP 5.6 on Apache and includes the extensions installed by `bin/php56/Dockerfile`.

Installed by that Dockerfile, beyond the base image: `curl`, `tokenizer`, `json`, `bcmath`, `mcrypt`, `pdo_mysql`, `pdo_sqlite`, `mysqli`, `zip`, `intl`, `mbstring`, `gd` (FreeType and JPEG), `xdebug-2.5.5`, and a separately compiled `odbc.so`. Composer is installed at `/usr/local/bin/composer`. Apache modules `ssl`, `rewrite`, and `headers` are enabled. `ServerName localhost` is set.

Provenance: **Implemented**.

The README's extension list also names `iconv`, `xml`, and `xmlrpc`, and it says to edit `./bin/webserver/Dockerfile` to add more. That path is not in this tree. Provenance: **Documented**. `iconv`, `xml`, and `xmlrpc` are not named in the Dockerfile's `docker-php-ext-install` list. Whether the base `php:5.6-apache` image already contains them was not checked. Status: **Unknown**.

### FR-003 — ODBC / FreeTDS client in the default PHP image

`bin/php56/Dockerfile` installs `unixodbc`, FreeTDS, and builds the PHP 5.6.40 ODBC extension. It appends an `freetds.conf` section:

```text
[mssql]
host = your_sql_server_host
port = 1433
tds version = 7.4
```

It registers a driver named `FreeTDS` in `odbcinst.ini`, pointing at `/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so`.

Provenance: **Implemented**. The host value is a placeholder. No `MSSQL_HOST` environment variable remains in the current compose file. The February compose file did pass `MSSQL_*` variables, and `76c21e3` removed them. A reachable SQL Server hostname is **Unknown / Requires Confirmation**.

`Dockerfile2` does not install ODBC or FreeTDS. Compose does not reference `Dockerfile2`. Provenance: **Implemented**.

### FR-004 — Sample environment is the configuration surface

Developers change ports, PHP version, database flavour, paths, and MySQL account settings in `.env`, starting from `sample.env`.

Provenance: **Documented** and **Implemented** (compose interpolation).

`PHPVERSION` values listed in `sample.env`: `php54`, `php56`, `php71`, `php72`, `php73`, `php74`, `php8`, `php81`, `php82`, `php83`. Only `php56` has a directory. `DATABASE` values listed: `mysql57`, `mysql8`, `mariadb103`, `mariadb104`, `mariadb105`, `mariadb106`. Only `mysql57` has a directory. Selecting another value makes the build context `./bin/<missing>`. Provenance: **Documented** list, **Implemented** directories.

### FR-005 — Historical Indawo database name

At `cc17467` and `2567dfc`, `MYSQL_DATABASE` was `indawo`. The README of those commits told developers to connect to database `indawo`. Provenance: **Implemented** and **Documented** in those commits. **Removed** from the compose file and README on `main`.

The current commented name is `indawo_online`. Provenance: **Documented** in `sample.env` only. It is not applied.

No requirement in the current README says the database must be named Indawo.

## Integrations

| System | Direction | Trigger | Data | Auth | Failure behaviour |
|---|---|---|---|---|---|
| Docker Hub (or the configured registry) for `php:5.6-apache`, `mysql:5.7`, `phpmyadmin`, `redis:latest` | Outbound pull | Image build or `compose up` | Image layers | Whatever the local Docker daemon uses. Not configured in this repo | **Unknown**. No retry policy in the repo |
| `archive.debian.org` | Outbound during image build | `apt-get` in the PHP Dockerfiles | Stretch packages | None in the Dockerfile | Build fails if apt fails. Not demonstrated |
| `https://www.php.net/distributions/php-5.6.40.tar.gz` | Outbound during image build | `wget` in `bin/php56/Dockerfile` | PHP source used only to compile `odbc.so` | None | Build fails if wget fails. Not demonstrated |
| `https://getcomposer.org/installer` | Outbound during image build | `curl` piped to `php` | Composer phar | None | Build fails if curl fails. Not demonstrated |
| PECL | Outbound during image build | `pecl install xdebug-2.5.5` | Xdebug | None | Build fails if pecl fails. Not demonstrated |
| Microsoft SQL Server via FreeTDS | Outbound from the web container at runtime, if an application opens ODBC | Application code, which is not in this repo | SQL on port 1433 to `your_sql_server_host` | Not set in the current compose file | **Unknown**. The DSN host is a placeholder |
| A mounted PHP application under `./www` | Bind mount, both directions (`rw`) | Container start | Developer files | Host filesystem permissions | **Unknown** which application |

The February image used `packages.microsoft.com` and `msodbcsql`. That Dockerfile was deleted in `76c21e3`. Provenance: **Removed**.

No webhook, mailer, queue worker, or object-storage client is defined.

## Constraints

- PHP image base is 5.6. Debian Stretch package feeds are rewritten to the Debian archive. Provenance: **Implemented**.
- MySQL client port and Redis port bind to `127.0.0.1`. Web and phpMyAdmin ports do not. Provenance: **Implemented**.
- `dev_build_container.sh` runs only on Linux and deletes MySQL data files under `./data/mysql/` before each build. Provenance: **Implemented**.
- `.gitignore` keeps `.env`, `config/`, `data/`, `logs/`, `www/`, and `buildtest/` out of git. Provenance: **Implemented**.
- The README says production use should at least switch the PHP handler from `mod_php` to `php-fpm` and restrict MySQL users by source IP. Neither change is implemented in the Dockerfiles. Provenance: **Documented** guidance. The images still use the `php:5.6-apache` layout (`apache2ctl` in the foreground). Provenance: **Implemented**.

## Removed behaviour (do not treat as current)

Present in `cc17467` / `2567dfc` and absent from `76c21e3`:

- Services named `php` and `mysql`.
- Mount `./src:/var/www/html`.
- Mount `/external/drive:/external`.
- Named volume `mysql_data`.
- `Dockerfile-php` with Microsoft ODBC Driver and `pdo_odbc`.
- Environment variables `MSSQL_HOST`, `MSSQL_DATABASE`, `MSSQL_USER`, `MSSQL_PASSWORD`.
- README sections for an external drive, database name `indawo`, and host-side ODBC DSNs.

Provenance: **Removed** (git history).

## Unknown / Requires Confirmation

- Which host application this stack is meant to run.
- Whether the commented `indawo_online` account is live.
- Whether `Dockerfile` or `Dockerfile2` is the image developers should build. Compose selects `Dockerfile` only by filename.
- Whether the volume line `-./filesystem:/var/www/filesystem` and the `FileSyem` mount are mistakes.
- Whether `CHANGELOG.md`, `docs/`, `sonar-project.properties`, and `sonarqube_scan.bat` from the 2026-09-28 scan exist anywhere except that scan host.
- Runtime result of `docker compose up`. This PRD did not build the images.
