Table of Contents
DokuWiki Docker Feasibility
DokuWiki Docker Feasibility looks at packaging this install as a public docker.io image runnable as docker run -it -v data:data yanevskiv:wiki. Short version: feasible and a genuinely good idea, but the exact invocation as phrased doesn't quite work — DokuWiki's persistent state is split across two places (data/ and conf/), not one, and a single volume mount has to be designed to cover both. The bigger cost driver is texrender's LaTeX toolchain, not DokuWiki itself.
The invocation, literally
-v data:data has two problems as written. First, Docker's -v needs an absolute container-side path — data isn't one, so this needs to be -v data:/var/www/yanevskiv.com/wiki/data (or wherever the image puts the app) rather than a bare relative name. Second, and more important: mounting only data/ doesn't capture everything that needs to persist. conf/local.php, conf/acl.auth.php, and conf/users.auth.php live outside data/ entirely (that's exactly why the main repo's .gitignore tracks data/ and conf/ as two separate exclusions), and all three hold state that must survive a container restart: your site title/baseurl, your ACL rules, your login credentials. If only data/ is mounted and the image is stopped and restarted from a fresh container, conf/ resets to whatever's baked into the image layer — which for a publicly distributed image can't be your real credentials anyway, since anyone who pulls yanevskiv:wiki from Docker Hub would see them in the image layer.
The fix is straightforward and is the standard Docker pattern for this: don't mount data/ directly, mount one directory (call it /state) that holds both concerns, and have the entrypoint symlink conf and data into subdirectories of it at container start (data/pages → /state/data/pages, conf/local.php → /state/conf/local.php, etc.). Then the actual command becomes something like docker run -it -v yanevskiv-state:/state yanevskiv:wiki — same spirit as what was asked for (one named volume, everything persists), just not literally data:data.
First-run bootstrapping
Because config now lives in the mounted volume rather than the image, a fresh volume means no conf/local.php/users.auth.php exist yet. The -it flag in the requested invocation is the right instinct here: the entrypoint script should check whether /state/conf/local.php exists on startup, and if not, run an interactive setup (site title, base URL, admin username/password — read prompts, since a TTY was requested) before generating those files and creating the admin account, then exec the actual web server in the foreground. Second and later runs skip straight to serving. This is the same pattern used by most self-hosted app images (Nextcloud, Gitea, etc.) and DokuWiki's own install.php wizard already does most of this logic — it would need to be driven non-interactively from the entrypoint instead of through a browser.
What bakes into the image (code, replaceable)
- DokuWiki core + the three remaining unavoidable core patches from DokuWiki Consolidation Feasibility: the
.mdextension cluster, thewikilink-wipCSS class, and the MenugetLink()overrides (if kept). lib/tpl/yanevskiv/— includinglogo.png/favicon.png, now that they live in the template rather thandata/media(a earlier, unrelated cleanup that happens to pay off here: site branding is now part of the disposable image layer, not runtime content, which is the right place for it in a container model. The tradeoff is that changing the logo now means rebuilding the image instead of uploading through the media manager).lib/plugins/{man,ace,texfigure,katex,markdowku}per the plugin split in DokuWiki Consolidation Feasibility —man,ace,texfigurebuilt from this repo's forks/originals,katex/markdowkufetched fresh from upstream at build time.- PHP 8.4 (matches what's running now) with the extensions already in use:
gd(thumbnails),mbstring,xml/dom/xmlreader/xmlwriter,zip,curl,json. All standard, nothing exotic.
What has to come from outside the image (state)
data/pages,data/media,data/meta,data/attic,data/index,data/cache,data/log,data/locks,data/tmp— DokuWiki's own writable runtime state, already excluded from the main git repo for the same reason.conf/local.php,conf/acl.auth.php,conf/users.auth.php— site identity and credentials, as covered above.
Build complexity: five repos, one image
The codebase currently spans the main repo, data/ (its own git repo, separately gitignored), lib/tpl/yanevskiv/ (own repo), lib/plugins/man/ (own repo), and soon lib/plugins/ace/ and lib/plugins/texfigure/ per the consolidation plan, plus katex/markdowku pulled fresh from the official plugin repository. None of this is a blocker — a Dockerfile just needs a build stage that clones/copies all of them into the right lib/plugins/* and lib/tpl/* paths before the final image layer — but it does mean the build process has more moving parts than “one repo, one docker build.” Worth scripting as a build.sh that does the fetching before docker build runs, rather than putting five git clones inline in the Dockerfile.
The size driver: `texrender`'s LaTeX toolchain
This is the real feasibility cost, not DokuWiki itself. bin/texrender shells out to a LaTeX toolchain (pdflatex/texfot and friends per its --texfot option) to turn latex_figure blocks into images. A full TeX Live install (texlive-full) runs several gigabytes; even a minimal scheme (texlive-latex-base + texlive-latex-extra + texlive-fonts-recommended) is realistically several hundred MB. That's on top of man-db + manpages (+ optionally manpages-dev) for the man plugin, which is comparatively cheap (tens of MB, and deliberately skips locale subdirectories per its own scan logic). A publicly distributed yanevskiv:wiki image is very unlikely to land under 1GB once the LaTeX toolchain is in it, which matters for a Docker Hub image meant for casual docker pull. Worth considering a smaller texlive scheme, or splitting into two image variants (yanevskiv:wiki without LaTeX, yanevskiv:wiki-tex with it) if latex_figure isn't used on every page.
Process model: one container, one foreground process
The current server presumably runs PHP-FPM behind a separate web server. For a single docker run (no docker-compose in the requested invocation), running two cooperating processes (nginx + php-fpm) needs a supervisor (s6-overlay, supervisord), which adds its own complexity. Simpler: base the image on php:8.4-apache with mod_php, since DokuWiki already ships .htaccess.dist with mod_rewrite rules for userewrite=1 — Apache is the natural fit here, no rewrite-rule translation to nginx config needed, and apache2-foreground is already a single-process, container-friendly entrypoint pattern.
A genuine side benefit: the permissions saga mostly disappears
Much of this session was spent on a recurring bug where editing template files reset their group ownership away from www-data, breaking PHP-FPM's read access, fixed with chgrp/chmod and eventually g+s on every directory. That entire class of bug exists because two separate identities — the human user iv and the web server www-data — share the same bare-metal filesystem. Inside a container, there's normally one identity: the process running Apache/PHP owns everything, full stop. If the workflow stays “edit files directly on the host, serve them from a container” (e.g. bind-mounting the repo into the container for live development), the same UID-mismatch bug can reappear depending on how host and container UIDs line up — but for the actual deployed/distributed image, this problem doesn't exist at all. Containerizing is close to a full fix for the underlying issue, not just a workaround for it.
Verdict
Feasible, and worth doing. Three real design decisions, not blockers: (1) restructure the volume story from “mount data/” to “mount one state directory that conf/ and data/ both symlink into,” (2) build an interactive first-run entrypoint that bootstraps conf/local.php and the admin account rather than baking credentials into the image, (3) decide whether the LaTeX toolchain ships in the main image or a separate heavier variant, since it's the dominant size cost by a wide margin.
