# 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 [[meta:dokuwiki-consolidation]]: the `.md` extension cluster, the `wikilink-wip` CSS class, and the Menu `getLink()` overrides (if kept). - `lib/tpl/yanevskiv/` — including `logo.png`/`favicon.png`, now that they live in the template rather than `data/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 [[meta:dokuwiki-consolidation]] — `man`, `ace`, `texfigure` built from this repo's forks/originals, `katex`/`markdowku` fetched 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 clone`s 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.