Files
MeshVault/docker/README.md
T

4.6 KiB

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:

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:

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.

./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.

./dev.sh assets

Watch mode rebuilds on template changes:

./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:

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.