Skip to content

[3.0][Testing] Add a Docker development environment for MySQL and PostgreSQL - #9317

Open
albertlast wants to merge 4 commits into
SimpleMachines:release-3.0from
albertlast:docker-dev-env
Open

[3.0][Testing] Add a Docker development environment for MySQL and PostgreSQL#9317
albertlast wants to merge 4 commits into
SimpleMachines:release-3.0from
albertlast:docker-dev-env

Conversation

@albertlast

@albertlast albertlast commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Note

This change was produced by an LLM. The code, the commit messages and this
description were all written by Claude (Anthropic), driven by @albertlast. It has
not yet had human code review.

Everything stated below was verified by actually running it — a full install from
an empty database on each engine — rather than only reasoned about. Even so, please
review it as untrusted work: it may be right about what it does while not being
what SMF would prefer stylistically or architecturally.

Description

This one is a proposal rather than a fix — please close it if a bundled dev
environment is not wanted in the repository.
It adds tooling only and changes no
forum code. It is the environment the other PRs in this batch were found and verified
in, so it is offered mainly so that work is reproducible.

docker compose up -d --build gives a working 3.0 checkout with no local PHP,
Composer, MySQL or PostgreSQL install:

Service URL / address Notes
Forum http://localhost:8080 PHP 8.4 on Apache
Mailpit http://localhost:8025 catches all mail(), nothing can be sent
Adminer http://localhost:8081 database browser
MySQL localhost:3307 3307 so it cannot collide with a local server
PostgreSQL localhost:5433 5433, same reason

Both engines SMF supports are in the stack, and MySQL is the default. Both
services always start, on separate volumes, so a forum can be installed on each and
switched between. SMF_DB_TYPE decides which one the generated Settings.php points
at:

SMF_DB_TYPE=postgresql docker compose up -d

Once the forum is installed Settings.php is what counts, and the variable no longer
has any effect. The entrypoint detects that case and says so in the log rather than
appearing to ignore the setting.

Built to match other/requirements.md: the required extensions (mbstring,
fileinfo, and both mysqli and pgsql, since SMF checks for pg_connect) and the
recommended ones (gd, intl, curl, exif, ftp, xsl, zip). The engine
settings SMF asks for are pinned at server level rather than left to whatever the
images happen to ship:

  • PostgreSQL: standard_conforming_strings = on, as requirements.md requires.
  • MySQL: utf8mb4 and InnoDB, matching SMF's own table DDL. The collation is
    deliberately left at the charset default — SMF writes CHARSET=utf8mb4 with no
    COLLATE, so its tables come out utf8mb4_0900_ai_ci on MySQL 8.4, and forcing a
    different server collation would only apply to objects SMF did not create and make
    the two diverge.

The entrypoint runs composer install, waits for whichever database was selected,
generates a Settings.php pointed at it and puts install.php in place, so a fresh
checkout is ready to install on first boot.

The PostgreSQL service is named postgres rather than db, and keeps db as a
network alias so a Settings.php written by an earlier revision of this branch still
resolves.

It does not disturb the existing CI checks

Everything lives under .docker/ on purpose. check-smf-index.php requires an
index.php in every directory but skips dot directories (that is how .github
passes today), and check-smf-license.php only inspects .php files — .docker/
contains none. Re-confirmed after adding the MySQL side: all four integrity scripts
in the build job exit 0 with this branch checked out.

The only tracked file outside .docker/ and compose.yaml is .gitignore, to add
/install.php (next to the existing /upgrade.php), /.env and the compose override
filenames.

Notes for review

  • Credentials are smf / smf / smf on both engines and are deliberately
    committed — this is a throwaway local environment, not something with secrets worth
    protecting.
  • compose.yaml works with no .env file; .docker/env.example is there for
    overriding ports, versions, credentials and the engine.
  • One wrinkle documented in .docker/README.md: the installer does not take its form
    defaults from Settings.php, it uses the hardcoded ones in the database API class,
    so the database step still has to be filled in by hand. The README lists the exact
    values for both engines.
  • php.ini, the vhost and the entrypoint are copied into the image rather than
    bind-mounted, so editing them needs docker compose up -d --build web, not a
    restart. An earlier revision of the README said restart, which was wrong.
  • Worth knowing when working in a git checkout: the UpdateUnicode scheduled task
    regenerates Sources/Unicode/*.php in place via file_put_contents(), and its
    output differs from what is committed by a handful of blank lines, so the working
    tree goes dirty on its own. Not caused by this PR, but it will be noticed by anyone
    using it.

How this was verified

PostgreSQL side: full teardown and rebuild (docker compose down -v, delete
Settings.php, up again) followed by a complete install from an empty database,
repeated several times while finding the other issues in this batch.

MySQL side: same, driven through every installer step against an empty database.

  • Steps 1 through 5 (welcome, writable check, database settings, forum settings,
    database population) all return HTTP 200.
  • 72 tables created, all InnoDB, all utf8mb4.
  • Admin account and finalize complete, install.php removed, and index.php then
    serves the new forum at HTTP 200.
  • Afterwards both volumes still hold their own independent forum, confirming the two
    engines do not interfere.

docker compose config validates, and all four build job integrity scripts pass.

One thing found while verifying, which this PR depends on

The installer cannot finish on this branch without #9316. Step 6, the admin
account step, dies with:

Uncaught Error: Typed static property SMF\User::$me must not be accessed before
initialization in /var/www/html/Sources/Time.php:191

which is exactly what #9316 fixes. Merging that branch in locally was what allowed the
MySQL install above to complete, and it was then dropped again so this PR stays
tooling-only. The code involved is in Sources/Maintenance/Tools/Install.php and is
not engine-specific, so it should affect a PostgreSQL install equally; it was only
observed here on MySQL.

This branch has also been brought up to date with release-3.0, which it was ten
commits behind.

Issues References (Fixes|Related|Closes)

  1. Related: [3.0] Load the current user before finalize() records dates #9316 (the installer cannot complete without it)

Provides a reproducible local stack so contributors can work on SMF
without installing PHP, Composer or PostgreSQL on the host:

- PHP 8.4 on Apache, with every extension other/requirements.md lists as
  required (mbstring, fileinfo, pgsql, mysqli) or recommended (gd, intl,
  curl, exif, ftp, xsl, zip).
- PostgreSQL 17, with standard_conforming_strings forced on at database
  level as SMF requires.
- Mailpit, so mail() is captured locally and nothing can be sent out.
- Adminer, for browsing the database.

The entrypoint runs composer install, waits for the database, generates a
Settings.php pointed at the db service and drops install.php into place,
so a fresh checkout is ready to install on first boot.

Everything lives under .docker/ because check-smf-index.php and
check-smf-license.php skip dot directories, so the environment cannot
break the file integrity checks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
albertlast and others added 2 commits July 29, 2026 23:50
SMF supports MySQL and PostgreSQL, and until now this environment only
offered one of them. Both database services now start, and SMF_DB_TYPE
decides which one the generated Settings.php points at. It defaults to
mysql, since that is what the great majority of installs run on.

The two engines keep separate volumes, so a forum can be installed on
each and switched between by deleting Settings.php and restarting.
Settings.php wins over SMF_DB_TYPE once it exists, and the entrypoint
says so rather than silently ignoring the variable.

The postgres service is renamed from `db` to say what it is, and keeps
`db` as a network alias so Settings.php files written by the previous
version still resolve.

Engine settings are pinned the same way the postgres side already pinned
standard_conforming_strings: utf8mb4 and InnoDB, matching SMF's own table
DDL. The collation is deliberately left at the charset default, because
SMF sets CHARSET without COLLATE, and forcing one here would diverge from
the tables it creates.

Also corrects the everyday-use notes: php.ini, the vhost and the
entrypoint are copied into the image, so editing them needs a rebuild
rather than a restart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@albertlast albertlast changed the title [3.0] Add a Docker development environment using PostgreSQL [3.0] Add a Docker development environment for MySQL and PostgreSQL Jul 29, 2026
PostgreSQL logs every statement that errors together with the SQL that
caused it, with no configuration needed, and the log is only on the
container stderr. That makes `docker compose logs postgres` the most
useful debugging tool in the stack, and nothing said so.

MySQL logs server errors only, never the client statement that failed,
so the note points out the asymmetry: now that mysql is the default
engine, a suspected SQL problem is worth reproducing on postgres.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdarwood007 jdarwood007 added this to the 3.0 Alpha 5 milestone Aug 1, 2026
@albertlast albertlast changed the title [3.0] Add a Docker development environment for MySQL and PostgreSQL [3.0][Testing] Add a Docker development environment for MySQL and PostgreSQL Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants