This commit is contained in:
1 parent
125eab3cd4
commit
045d3a8fd3
8 files changed
+375
-65
No files matched your search
+77
-54
@@ -3,7 +3,8 @@
|
||||
This stack runs PHP 8.3/Apache, MySQL 8.4 LTS, and phpMyAdmin 5.2. No Node build,
|
||||
registry, or separate Komodo Build resource is required. The app image is built
|
||||
on your Docker host. MySQL has no published port. Database, application sessions,
|
||||
and phpMyAdmin sessions use persistent named volumes.
|
||||
and phpMyAdmin sessions use persistent named volumes. Two one-shot services import
|
||||
an initial SQL dump safely and apply migrations before Apache starts.
|
||||
|
||||
To build/publish the app in Gitea Actions instead of on the server, see
|
||||
[the image build guide](image-build.md), including registry secrets and Komodo
|
||||
@@ -32,9 +33,10 @@ secrets. Generate each password with `openssl rand -hex 32`. Use Komodo secrets
|
||||
if available; do not commit the populated environment to Git. Leave the environment
|
||||
file path at `.env`: Komodo writes it and passes it to Compose.
|
||||
|
||||
Deploy the Stack. **The app may initially be unhealthy** until you explicitly
|
||||
import the base database and run migrations below. Do not enable a deploy
|
||||
`--wait` flag on this first launch: it cannot become ready before that setup.
|
||||
Before deploying, transfer your trusted initial SQL dump to the Docker host and
|
||||
set `DB_INIT_SQL_PATH` as described below. Deploy the Stack: startup waits for
|
||||
MySQL, runs `db-init`, runs `migrate`, then starts the app. The one-shot services
|
||||
should finish with exit code 0; they do not remain running.
|
||||
|
||||
For a files-on-host Stack instead, put the repository on the server, select
|
||||
**Files on host**, set Run directory to its absolute path, and use the same
|
||||
@@ -42,52 +44,70 @@ Compose/build/environment settings.
|
||||
|
||||
Official reference: [Komodo Compose Stacks](https://komo.do/docs/deploy/compose).
|
||||
|
||||
## 2. Import the database once
|
||||
|
||||
On the Docker server, change to the Stack's checked-out **run directory**. The
|
||||
commands below assume the project name `recruitment-hc` and Komodo's default
|
||||
`.env` file; if you choose another project name/env path, adjust **every** command
|
||||
accordingly. Never run commands against a different project by accident.
|
||||
|
||||
Wait for `db` to be healthy:
|
||||
|
||||
```sh
|
||||
docker compose --env-file .env -p recruitment-hc ps
|
||||
```
|
||||
## 2. Automatic database initialization
|
||||
|
||||
Obtain a trusted recruitment SQL export containing `in_daper`, `in_soal`, and
|
||||
`in_jawab`. Transfer it privately to a path **outside the checkout/document root**,
|
||||
for example `/srv/recruitment-private/initial.sql`, with restricted permissions.
|
||||
The repository currently also tracks an export under `DB/`; it may contain
|
||||
personal data and existing accounts. Keep the repository private, review/sanitize
|
||||
any export used in production, and remove unwanted demo/test access before opening
|
||||
the site. Neither `DB/` nor any export is included in the image or auto-imported.
|
||||
`in_jawab`. Transfer it privately to the **Docker host**, outside the
|
||||
checkout/document root, for example `/srv/recruitment-private/initial.sql`.
|
||||
Restrict access to the file and set this in the Stack Environment (or `.env`):
|
||||
|
||||
**Only import into a new, empty database.** Dumps can contain `DROP TABLE` and
|
||||
existing accounts/passwords. Check first; this should return **no table names**:
|
||||
|
||||
```sh
|
||||
docker compose --env-file .env -p recruitment-hc exec -T db sh -c \
|
||||
'MYSQL_PWD="$MYSQL_PASSWORD" mysql -u "$MYSQL_USER" "$MYSQL_DATABASE" -e "SHOW TABLES"'
|
||||
```dotenv
|
||||
DB_INIT_SQL_PATH=/srv/recruitment-private/initial.sql
|
||||
```
|
||||
|
||||
If it is empty, import and apply the migrations:
|
||||
For local Docker use, the default is
|
||||
`./DB/recruitment_local_2026-10-14.sql`. That dump contains personal data and
|
||||
existing accounts, not just schema. Review/sanitize production exports and remove
|
||||
unwanted demo/test access before opening the site. Dumps are not shipped in the
|
||||
app image or fetched from Git. The file is mounted read-only into `db-init`;
|
||||
it must exist on the Docker host even on later deployments. A missing path fails
|
||||
startup instead of silently creating a directory. Dumps must not reference the
|
||||
reserved `rec_bootstrap_state` safety table; exclude it from exports/backups using
|
||||
the command in section 5. This prevents a restored marker from masking a failed
|
||||
import.
|
||||
|
||||
Normal deployment handles setup automatically:
|
||||
|
||||
1. `db` becomes healthy.
|
||||
2. `db-init` imports the dump **only if the database contains no tables or views**.
|
||||
A persistent `rec_bootstrap_state` table records `importing` before the import
|
||||
and `imported` only after success and validation of the three base tables.
|
||||
3. On subsequent deployments, an `imported` marker and the base tables skip the
|
||||
dump entirely. A pre-existing database without a marker is accepted only if
|
||||
all seven recruitment tables are present. Partial/unexpected databases are
|
||||
refused, not overwritten. This check cannot validate the contents of a dump
|
||||
imported outside this setup; review such databases yourself before deployment.
|
||||
4. `migrate` applies the idempotent admin/exam migrations and validates readiness.
|
||||
5. `app` starts only after both one-shot services exit successfully.
|
||||
|
||||
On the Docker server, change to the Stack's checked-out **run directory**. The
|
||||
commands below assume project name `recruitment-hc` and `.env`; adjust every
|
||||
command if your Stack uses different settings.
|
||||
|
||||
```sh
|
||||
docker compose --env-file .env -p recruitment-hc exec -T db sh -c \
|
||||
'MYSQL_PWD="$MYSQL_PASSWORD" mysql -u "$MYSQL_USER" "$MYSQL_DATABASE"' \
|
||||
< /srv/recruitment-private/initial.sql
|
||||
|
||||
docker compose --env-file .env -p recruitment-hc exec -T app \
|
||||
php /usr/local/share/recruitment/migrate.php
|
||||
docker compose --env-file .env -p recruitment-hc ps -a
|
||||
docker compose --env-file .env -p recruitment-hc logs db-init migrate
|
||||
```
|
||||
|
||||
The migration command requires the three base tables, creates the admin and exam
|
||||
protection tables, and handles the historical admin identity schema when needed.
|
||||
It can be rerun without resetting users or test progress. Migrations are explicit,
|
||||
not run automatically on every container restart. Back up before applying them to
|
||||
an existing database. Future migrations must be added to the migration runner as
|
||||
part of their release.
|
||||
The import guard has a database-free regression suite:
|
||||
`python3 dev/test-db-init.py`.
|
||||
|
||||
**Failed import:** SQL DDL is not transactional. An `importing` marker deliberately
|
||||
blocks retries, including when only some tables were restored. Inspect the logs
|
||||
and affected database, then restore a trusted backup or use a separately verified
|
||||
empty database/volume. Do not delete the marker or run a dump over partial data
|
||||
blindly. Never delete the production volume merely to retry setup.
|
||||
|
||||
Migrations can be rerun without resetting users or test progress. They run during
|
||||
Compose deployment, not on an individual Apache container restart. Back up before
|
||||
deploying changes against an existing database. Add future migrations to the
|
||||
migration runner as part of their release. If a migration fails, fix the cause and
|
||||
rerun setup without reimporting:
|
||||
|
||||
```sh
|
||||
docker compose --env-file .env -p recruitment-hc run --rm migrate
|
||||
docker compose --env-file .env -p recruitment-hc up -d
|
||||
```
|
||||
|
||||
If you need a new admin account, run this from an **interactive SSH terminal**:
|
||||
|
||||
@@ -169,17 +189,17 @@ Never expose phpMyAdmin directly on an unrestricted public HTTP port.
|
||||
Add these new settings from `.env.example` to the Komodo Stack Environment and
|
||||
redeploy. `PHPMYADMIN_PORT` defaults to `8087`; `PHPMYADMIN_UPLOAD_LIMIT` defaults
|
||||
to `64M`. For browser imports, adjust your reverse proxy's upload size/timeouts as
|
||||
needed; large dumps are better imported using the CLI command in section 2.
|
||||
Browser imports can also overwrite data: only import into a verified empty
|
||||
database, then run the migration command. No database initialization is automated.
|
||||
needed; large dumps are better handled by the setup service in section 2.
|
||||
Browser imports can also overwrite data. Prefer the automatic `db-init` service
|
||||
for first-time setup; do not import another dump over an initialized database.
|
||||
|
||||
## 4. Verify
|
||||
|
||||
```sh
|
||||
docker compose --env-file .env -p recruitment-hc ps
|
||||
docker compose --env-file .env -p recruitment-hc ps -a
|
||||
curl --fail http://127.0.0.1:8086/healthz
|
||||
curl --fail http://127.0.0.1:8087/ > /dev/null
|
||||
docker compose --env-file .env -p recruitment-hc logs --tail=100 app db phpmyadmin
|
||||
docker compose --env-file .env -p recruitment-hc logs --tail=100 app db db-init migrate phpmyadmin
|
||||
```
|
||||
|
||||
Adjust the curl address if you changed the bind IP or port. `/healthz` returns
|
||||
@@ -211,19 +231,20 @@ snapshot for InnoDB. Include any active test data when planning maintenance.
|
||||
umask 077
|
||||
mkdir -p /srv/recruitment-private/backups
|
||||
docker compose --env-file .env -p recruitment-hc exec -T db sh -c \
|
||||
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysqldump -u root --single-transaction --routines --triggers --no-tablespaces "$MYSQL_DATABASE"' \
|
||||
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysqldump -u root --single-transaction --routines --triggers --no-tablespaces --ignore-table="$MYSQL_DATABASE.rec_bootstrap_state" "$MYSQL_DATABASE"' \
|
||||
> "/srv/recruitment-private/backups/recruitment-$(date +%Y%m%d-%H%M%S).sql"
|
||||
```
|
||||
|
||||
Check the command's exit status and backup contents before relying on the file.
|
||||
SQL backups contain personal data and password hashes; restrict and protect them.
|
||||
Restore using the import command in section 2 **only after selecting a new empty
|
||||
database or explicitly approving replacement of the target data**; migrate after
|
||||
restoring if needed.
|
||||
To restore into a new empty stack, set `DB_INIT_SQL_PATH` to the trusted backup
|
||||
and deploy; initialization and migrations run automatically. Restoring over an
|
||||
existing database requires a separate, explicitly approved recovery procedure;
|
||||
normal startup never replaces its tables.
|
||||
|
||||
To update, back up, pull the new commit in Komodo and redeploy with **Run build**
|
||||
enabled. The database volume is reused; imports are never repeated automatically.
|
||||
Apply migration changes explicitly when a release requires them. Rolling back an
|
||||
enabled. The database volume is reused; successful imports are never repeated.
|
||||
The migration service runs before the updated app starts. Rolling back an
|
||||
image does not undo schema changes; use a tested database restore if necessary.
|
||||
Image tags track compatible patch releases; consider pinning tested image digests
|
||||
in production for reproducible upgrades.
|
||||
@@ -246,11 +267,13 @@ From the repository root on the server:
|
||||
```sh
|
||||
cp .env.example .env
|
||||
chmod 600 .env
|
||||
# Edit .env and replace both password placeholders before proceeding.
|
||||
# Edit .env: replace both passwords and set DB_INIT_SQL_PATH to your trusted dump.
|
||||
# The SQL file must already exist on this Docker host.
|
||||
docker compose --env-file .env -p recruitment-hc config --quiet
|
||||
docker compose --env-file .env -p recruitment-hc up -d --build
|
||||
```
|
||||
|
||||
Then follow sections 2–5. Docker uses its own environment-backed
|
||||
Setup is automatic. Inspect `db-init`/`migrate` logs, create an admin as needed
|
||||
(section 2), then follow sections 3–5. Docker uses its own environment-backed
|
||||
`includes/conn.php` baked into the image; it never reads or overwrites the host's
|
||||
private `includes/conn.php`. Standalone PHP/local preview behavior is unchanged.
|
||||
Reference in new issue
Block a user