115 lines
4.6 KiB
Markdown
115 lines
4.6 KiB
Markdown
# Development containers (M1)
|
|
|
|
Four-service Docker Compose stack: nginx, unprivileged PHP-FPM, PostgreSQL and
|
|
an assets container for Tailwind CSS builds. The application layer (Slim 4,
|
|
PHP-DI, Monolog) is wired, but there is no catalog schema, migration runner or
|
|
asset pipeline beyond Tailwind. Do not expose this stack to the Internet.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker Engine/Desktop with Linux containers and Docker Compose v2+.
|
|
- No host PHP, Composer or Node is required.
|
|
|
|
## First start
|
|
|
|
From the repository root, copy `.env.example` to `.env` and edit
|
|
`MESHVAULT_DB_PASSWORD` to a private, nonempty value. Never commit `.env` or print
|
|
expanded Compose configuration in shared logs; use `docker compose config --quiet`.
|
|
|
|
Create a **new dedicated** `library` directory (`mkdir library`). Do not use an
|
|
existing collection. On Linux, give container UID/GID 33 ownership of that new
|
|
empty directory, for example `sudo chown 33:33 ./library` and
|
|
`sudo chmod 750 ./library`. Alternatively, after building, use the narrowly scoped
|
|
one-off command below **only for this new empty directory**:
|
|
|
|
```sh
|
|
docker compose build app
|
|
docker compose run --rm --no-deps --user root app chown 33:33 /var/lib/meshvault/library
|
|
docker compose config --quiet
|
|
docker compose up -d --wait
|
|
```
|
|
|
|
Also ensure `public/build` is writable by the assets container user (`node`, UID
|
|
1000). On Linux, run:
|
|
|
|
```sh
|
|
mkdir -p public/build
|
|
chown 1000:1000 public/build
|
|
```
|
|
|
|
Docker Desktop bind permissions differ; verify writability using the runtime
|
|
identity rather than assuming host chmod works. The stack never automatically
|
|
creates or changes ownership of a configured library directory.
|
|
|
|
## Task wrappers
|
|
|
|
Use `dev.sh` (POSIX) or `dev.ps1` (PowerShell) from the repository root. They are
|
|
independent of your current working directory and propagate exit codes.
|
|
|
|
```sh
|
|
./dev.sh up # build and start services
|
|
./dev.sh down # stop services (volume removal is forbidden)
|
|
./dev.sh test # run composer test inside the app container
|
|
./dev.sh lint # run composer lint inside the app container
|
|
./dev.sh assets # build minified CSS inside the assets container
|
|
./dev.sh watch # start Tailwind watch inside the assets container
|
|
./dev.sh migrate # run database migrations (M2 #12)
|
|
./dev.sh seed # seed default reference data (M2 #12)
|
|
```
|
|
|
|
`down --volumes` and `down -v` are blocked by the wrapper. Never remove the named
|
|
`pgdata` volume or the library bind.
|
|
|
|
## Asset builds
|
|
|
|
Assets are built inside the `assets` service using a locked `package-lock.json`.
|
|
The generated `public/build/app.css` is served statically by nginx.
|
|
|
|
```sh
|
|
./dev.sh assets
|
|
```
|
|
|
|
Watch mode rebuilds on template changes:
|
|
|
|
```sh
|
|
./dev.sh watch
|
|
```
|
|
|
|
## Verification
|
|
|
|
Open http://127.0.0.1:8090/ for the landing page. `docker compose exec app id`
|
|
should report UID/GID 33. Check a disposable library write without becoming root:
|
|
|
|
```sh
|
|
docker compose exec app php -r '$p = getenv("MESHVAULT_LIBRARY_DIR") . "/write-check"; if (file_put_contents($p, "ok") === false) { exit(1); } unlink($p);'
|
|
```
|
|
|
|
`down` preserves the named `pgdata` volume and library bind. Changing database
|
|
credentials in `.env` does not change credentials in an initialized PostgreSQL
|
|
volume. Back up data before upgrades.
|
|
|
|
## Settings and boundaries
|
|
|
|
`.env.example` documents every current setting: Compose project, HTTP host/port,
|
|
DB name/user/password, host library path and absolute container library path.
|
|
The container library path must stay outside `/var/www/html` and must not overlap
|
|
system paths. The only required non-default value is the database password.
|
|
The default project is `meshvault-m1`; HTTP binds localhost:8090. Only nginx has a
|
|
published port. PostgreSQL readiness gates app startup. FPM itself runs as
|
|
`www-data`, not just its workers. nginx mounts only `public/` and executes only
|
|
`/index.php`; source, credentials and library are not web mounts.
|
|
|
|
Source mounts are explicit and read-only. No host `vendor` or `node_modules` is
|
|
mounted; dependencies are installed inside images from lockfiles. No Docker socket
|
|
is mounted. Startup configuration validation is provided by the entrypoint script.
|
|
|
|
Image branches: PHP 8.3 FPM Bookworm (security support to December 2027), PostgreSQL
|
|
17 Bookworm (support to November 2029), nginx 1.30 Alpine (stable), Node 24
|
|
Bookworm slim (LTS). Tags are versioned but move with patch updates, not digest
|
|
locks. PHP 8.3 compatibility is retained.
|
|
|
|
Remote verification uses only `/home/keith/Projects/MeshVault` after confirming
|
|
HOME, explicit project `meshvault-m1`, and an explicit source-only copy manifest.
|
|
Access from another machine via `ssh -L 8090:127.0.0.1:8090 keith@192.168.2.23`.
|
|
Never attach original collections or change unrelated services.
|