Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ This repository is a fork of the MediaWiki application image from the [Canasta](
| Extensions (add / update / remove) | [docs/extensions.md](docs/extensions.md) |
| Patching | [docs/patching.md](docs/patching.md) |
| Deployment & runtime | [docs/deployment.md](docs/deployment.md) |
| Bind mounts → named volumes (WIK-2057) | [docs/bind-mounts-to-volumes.md](docs/bind-mounts-to-volumes.md) |
| Upgrades (MW minor, LTS, PHP) | [docs/upgrades/](docs/upgrades/) |
| E2E tests | [e2e/README.md](e2e/README.md) |

Expand Down
20 changes: 14 additions & 6 deletions docker-compose.sample.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# This is a dev/debug compose file
#
# WIK-2057: all writable state lives in Docker named volumes (taqasta_*).
# Only read-only config/log-viewing mounts remain as bind mounts.
# Existing deployments using bind-mount directories can migrate their data
# with scripts/migrate-binds-to-volumes.sh (see docs/bind-mounts-to-volumes.md).
x-web-environment: &x-web-environment
MW_ADMIN_USER: ${MW_ADMIN_USER:-admin}
MW_ADMIN_PASS: ${MW_ADMIN_PASS:-Passsw0rd!}
Expand All @@ -21,9 +26,10 @@ x-web-environment: &x-web-environment
MW_ENABLE_JOB_RUNNER: false

x-web-volumes: &x-web-volumes
- mediawiki:/mediawiki
- ./logstest:/var/log/app
- ./LocalSettings.dev.php:/mediawiki/config/settings/LocalSettings.dev.php
- taqasta_mw_volume:/mediawiki
# WIK-2057: read-only host mounts for config and log inspection
- ./logstest:/var/log/app:ro
- ./LocalSettings.dev.php:/mediawiki/config/settings/LocalSettings.dev.php:ro

x-service-worker: &x-service-worker
build:
Expand Down Expand Up @@ -59,7 +65,7 @@ services:
- MYSQL_ROOT_PASSWORD=${MW_DB_INSTALLDB_PASS:-mediawiki}
- MYSQL_DATABASE=${MW_DB_NAME:-mediawiki}
volumes:
- mysql:/var/lib/mysql
- taqasta_db_data:/var/lib/mysql

web:
build:
Expand Down Expand Up @@ -119,8 +125,10 @@ services:
php $$MW_HOME/maintenance/run.php runJobs --memory-limit max --wait --type webVideoTranscodePrioritized

volumes:
mediawiki:
mysql:
taqasta_mw_volume:
name: taqasta_mw_volume
taqasta_db_data:
name: taqasta_db_data

networks:
traefik-public:
Expand Down
26 changes: 17 additions & 9 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# # Note: this is a dummy Compose file for CI, do not modify or use it until you know what you're doing
#
# WIK-2057: all writable state lives in Docker named volumes (taqasta_*).
# Read-only config/test mounts stay as bind mounts.
services:
db:
image: mysql:8.0
Expand All @@ -12,7 +15,7 @@ services:
- MYSQL_DATABASE=${MW_DB_NAME:-mediawiki}
volumes:
- initdb:/docker-entrypoint-initdb.d
- mysql:/var/lib/mysql
- taqasta_db_data:/var/lib/mysql

web:
image: ${TAQASTA_IMAGE:-taqasta-web}
Expand Down Expand Up @@ -40,8 +43,9 @@ services:
- PHP_UPLOAD_MAX_FILESIZE=500M
- PHP_POST_MAX_SIZE=500M
volumes:
- mediawiki:/mediawiki
- ./e2e/LocalSettings.php:/var/www/mediawiki/w/_settings/LocalSettings.php
- taqasta_mw_volume:/mediawiki
# Read-only config mount (WIK-2057): test settings stay a bind
- ./e2e/LocalSettings.php:/var/www/mediawiki/w/_settings/LocalSettings.php:ro

e2e:
build:
Expand All @@ -54,14 +58,18 @@ services:
ports:
- "9323:9323"
volumes:
- ./e2e/playwright.config.ts:/e2e/playwright.config.ts
- ./e2e/tests/:/e2e/tests
- ./e2e/fixtures/:/e2e/fixtures
- ./e2e/playwright-report/:/e2e/playwright-report
# WIK-2057: read-only test inputs stay as bind mounts
- ./e2e/playwright.config.ts:/e2e/playwright.config.ts:ro
- ./e2e/tests/:/e2e/tests:ro
- ./e2e/fixtures/:/e2e/fixtures:ro
# WIK-2057: report output moved to a named volume; copy it back with:
# docker compose --profile e2elocal cp e2e:/e2e/playwright-report ./playwright-report
profiles:
- e2elocal

volumes:
mediawiki:
mysql:
taqasta_mw_volume:
name: taqasta_mw_volume
taqasta_db_data:
name: taqasta_db_data
initdb:
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Extensions, skins, and patches are defined in [values.yml](../values.yml).
| Adding, updating, and removing extensions | [extensions.md](extensions.md) |
| Applying patches | [patching.md](patching.md) |
| Deployment, env vars, enabling extensions | [deployment.md](deployment.md) |
| Bind mounts → named volumes migration | [bind-mounts-to-volumes.md](bind-mounts-to-volumes.md) |
| Minor MediaWiki point releases | [upgrades/mediawiki-minor.md](upgrades/mediawiki-minor.md) |
| LTS MediaWiki upgrades | [upgrades/mediawiki-major.md](upgrades/mediawiki-major.md) |
| PHP version upgrades | [upgrades/php.md](upgrades/php.md) |
Expand Down
60 changes: 60 additions & 0 deletions docs/bind-mounts-to-volumes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Migrating writable bind mounts to Docker named volumes (WIK-2057)

All writable Taqasta state now lives in **Docker named volumes** instead of host bind-mount directories:

| Data | Named volume | Was (legacy layout) |
|------|--------------|---------------------|
| MySQL datadir | `taqasta_db_data` | `./mysql` bound to `/var/lib/mysql` |
| MediaWiki volume (uploads, images, config) | `taqasta_mw_volume` | `./images` and friends |

Read-only configuration files (custom `LocalSettings`, `.htaccess` overrides, dev log viewers) intentionally remain bind mounts — they are not writable state and are versioned with your deployment.

## Why

Bind-mounted directories caused recurring ownership mismatches between the container user and the host user, permission drift after image upgrades, and inconsistent behavior between hosts. Named volumes fix these issues ([WIK-476](https://wikiteq.atlassian.net/browse/WIK-476), [WIK-2057](https://wikiteq.atlassian.net/browse/WIK-2057)), keep data persistent across container restarts and rebuilds, and make deployments more portable.

Kubernetes deployments are **unaffected**: they use `PersistentVolumeClaim`s and were already volume-based.

## What changes for existing VPS clients

If your deployment stores the database or wiki data in host directories that are bind-mounted into containers, do a one-time migration when adopting the updated compose files. Until the data is copied into the named volumes, switching compose files would start with *empty* volumes.

The repository ships an idempotent migration tool: [`scripts/migrate-binds-to-volumes.sh`](../scripts/migrate-binds-to-volumes.sh).

### Upgrade steps

1. **Back up** (as you would before any upgrade): `mysqldump` plus a file-level copy of the images directory.
2. Pull the updated Taqasta files, then run a dry run from the deployment directory:

```bash
sh scripts/migrate-binds-to-volumes.sh
```

It prints what it would migrate (file counts and byte totals) and changes nothing.
3. Review the plan, then apply it:

```bash
sh scripts/migrate-binds-to-volumes.sh --apply
```

The script stops the stack (`docker compose stop`; containers are kept), seeds the `taqasta_db_data` / `taqasta_mw_volume` volumes from the legacy directories using a temporary helper container, verifies file counts and byte totals against the source, and renames each migrated directory to `<name>.migrated-<timestamp>`; nothing is ever deleted (apply mode only; a dry run neither stops services nor touches disk).
4. Start the stack on the new compose files:

```bash
docker compose -f docker-compose.sample.yml up -d
```

5. Smoke-test the wiki (login, page edit, file upload). Keep the `*.migrated-<timestamp>` directories until you are satisfied; they double as the rollback snapshot.

Useful options: `-f FILE` for custom compose files (repeatable), `-p NAME` for a specific project name, `--db-dir DIR` / `--mw-dir DIR` if your legacy directories are not at `./mysql` / `./images`, and `--skip-db` / `--skip-mw` to migrate only one of them. Set `TAQASTA_DB_VOLUME` / `TAQASTA_MW_VOLUME` if your deployment overrides the volume names.

### Rollback

Stop the stack, point compose back at the previous file (the one using bind mounts), rename `<name>.migrated-<timestamp>` back to `<name>` if needed, and start the stack. The named volumes can be removed later once the rollback window closes.

## Notes

- The migration runs entirely on the client server by the client/operator; WikiTeq does not run anything remotely as part of this change.
- The helper container uses `rsync` when available and falls back to `cp -a`. Re-runs never overwrite existing files in a volume, so interrupted migrations can simply be re-run.
- Fresh installs have nothing to migrate: new stacks create empty named volumes on first start.
- The volume names are pinned literals in the compose files (`taqasta_db_data`, `taqasta_mw_volume`), not `${VAR:-default}` interpolations, so operators running multiple stacks on one host must edit the YAML to rename them per deployment.
Loading
Loading