Bądź na bieżąco - RSS

DokuWiki w Dockerze: TypeError ModeRegistry po aktualizacji do Mort

29 sierpnia, 2026 | Brak Komentarzy | Kategoria: Bez kategorii, Linux, Porady

Komunikat DokuWiki ModeRegistry TypeError w przeglądarce

Jeśli po aktualizacji obrazu Dockera Twoja wiki wita Cię różowym prostokątem z komunikatem DokuWiki ModeRegistry TypeError, masz do czynienia z problemem, którego nie naprawi żadna kolejna wersja kontenera. Przyczyna leży bowiem nie w obrazie, tylko w Twoim własnym wolumenie z konfiguracją. Poniżej opisuję pełną diagnozę i procedurę naprawy, którą przeszedłem na produkcyjnej instalacji.

Objaw: biała strona i komunikat o błędzie

Po przejściu obrazu lscr.io/linuxserver/dokuwiki:latest na wydanie 2026-07-14b „Mort” wiki przestaje się otwierać. Zamiast treści pojawia się komunikat:

TypeError: dokuwiki\Parsing\ModeRegistry::__construct(): Argument #1 ($syntax)
must be of type string, null given, called in /app/www/public/inc/parserutils.php on line 239

Poniżej dopisek, że wystąpił nieprzewidziany błąd i że więcej informacji trafiło do logu. Sam log niewiele wyjaśnia, bo zawiera ten sam stos wywołań. Kluczowa informacja jest już w pierwszej linii: do konstruktora klasy trafia null tam, gdzie oczekiwany jest łańcuch znaków.

DokuWiki ModeRegistry TypeError: skąd się bierze

Wydanie „Mort” wprowadziło opcjonalne natywne parsowanie Markdown. Steruje nim nowe ustawienie syntax, które przyjmuje wartości dw, md, dw+md lub md+dw. W funkcji p_get_instructions() znajduje się linia:

$registry = new ModeRegistry($syntax ?? $conf['syntax']);

Operator ?? zabezpiecza wyłącznie zmienną $syntax. Jeżeli w tablicy konfiguracji nie ma klucza syntax, wyrażenie zwraca null, a typowany konstruktor natychmiast rzuca wyjątkiem. Stąd komunikat DokuWiki ModeRegistry TypeError.

Wartość domyślna tego klucza jest zdefiniowana w pliku conf/dokuwiki.php, w linii 20:

$conf['syntax']      = 'dw';              //syntax flavor: 'dw', 'md', 'dw+md', 'md+dw'

I tutaj dochodzimy do sedna. Plik conf/dokuwiki.php należy do rdzenia DokuWiki, ale w obrazie linuxserver katalog /app/www/public/conf jest dowiązaniem symbolicznym do /config/dokuwiki/conf. Ten katalog leży w trwałym wolumenie i nie jest odświeżany przy aktualizacji obrazu, bo przechowuje także Twoją konfigurację. Efekt: nowy kod aplikacji spotyka się z plikiem domyślnych ustawień sprzed półtora roku, w którym klucza syntax po prostu jeszcze nie było.

Dlaczego czekanie na nowy obraz nic nie da

Pierwszy odruch po takiej awarii jest naturalny: poczekam na kolejny latest, pewnie to naprawią. W tym przypadku to strata czasu. Aktualizacja obrazu podmienia kod w /app/www/public, czyli dokładnie tę połowę układanki, która już jest nowa. Feralny plik siedzi w wolumenie i żadna wersja obrazu go nie dotknie.

Z perspektywy zespołu linuxserver nie ma tu też nic do naprawienia w samym obrazie, bo oni jedynie pakują upstream. Z perspektywy DokuWiki problem również nie istnieje, ponieważ przy klasycznej instalacji katalog conf zawsze przyjeżdża świeży razem z resztą plików. Kombinacja trwałego wolumenu i pliku rdzenia trzymanego w tym samym miejscu co konfiguracja użytkownika to sytuacja specyficzna dla konteneryzacji.

Diagnoza w trzydzieści sekund

Zanim cokolwiek zmienisz, potwierdź hipotezę jedną komendą na hoście:

grep -n "\['syntax'\]" /var/lib/docker/volumes/dokuwiki_config/_data/dokuwiki/conf/dokuwiki.php

Pusty wynik oznacza, że klucza nie ma i diagnoza się potwierdza: masz do czynienia z klasycznym DokuWiki ModeRegistry TypeError wywołanym przestarzałym plikiem konfiguracji. Uwaga na drobiazg: samo grep -c syntax bez nawiasów potrafi zwrócić jedynkę, ponieważ w nagłówku pliku znajduje się komentarz o składni PHP. Liczy się konkretna definicja zmiennej, nie samo słowo.

Obejście doraźne, żeby wiki wstała od razu

Jeśli potrzebujesz działającej strony natychmiast, dopisz brakującą wartość do własnej konfiguracji, która ma pierwszeństwo nad domyślną:

cd /var/lib/docker/volumes/dokuwiki_config/_data/dokuwiki/conf
cp local.php local.php.bak
echo "\$conf['syntax'] = 'dw';" >> local.php
rm -rf ../data/cache/*
docker restart dokuwiki

Sprawdź jeszcze właściciela pliku poleceniem ls -l. Dopisujesz jako root, więc jeśli local.php zostałby utworzony od zera, menedżer konfiguracji w panelu webowym straciłby możliwość zapisu. W razie potrzeby wyrównaj uprawnienia do swojego PUID i PGID.

To rozwiązanie łata jednak tylko jeden brakujący klucz. „Mort” przyniósł ich więcej, więc prędzej czy później trafisz na kolejny objaw tego samego schorzenia.

Właściwa naprawa krok po kroku

Docelowo należy odświeżyć wszystkie pliki rdzenia w katalogu conf, zostawiając nietknięte pliki użytkownika. Wbrew pozorom rozróżnienie jest proste, bo obie grupy nie mają wspólnych nazw.

Krok 1: zebranie danych

docker exec dokuwiki cat /app/www/public/VERSION
docker exec dokuwiki id abc

CONF=/var/lib/docker/volumes/dokuwiki_config/_data/dokuwiki/conf
DATA=/var/lib/docker/volumes/dokuwiki_config/_data/dokuwiki/data
TAG=release-2026-07-14b

Użytkownik abc to standardowe konto w obrazach linuxserver, a jego identyfikatory przydadzą się przy ustawianiu właściciela plików. Wartość TAG dopasuj do tego, co zwróci VERSION.

Krok 2: pobranie czystych plików rdzenia

mkdir -p /tmp/dw && cd /tmp/dw
curl -sL -o dw.tar.gz "https://codeload.github.com/dokuwiki/dokuwiki/tar.gz/refs/tags/${TAG}"
tar xzf dw.tar.gz
SRC=/tmp/dw/dokuwiki-${TAG}/conf
grep -n "\['syntax'\]" "$SRC/dokuwiki.php"

Ostatnia komenda musi pokazać linię 20 z definicją dw. Jeśli jej nie widzisz, pobrałeś niewłaściwe wydanie.

Krok 3: podgląd różnic

diff -rq "$SRC" "$CONF"

Wpisy typu Only in $CONF dotyczące local.php, acl.auth.php, users.auth.php, plugins.local.php oraz plików *.local.conf są całkowicie normalne. To Twoje dane i one zostają na miejscu.

Krok 4: kopia zapasowa i zatrzymanie kontenera

docker stop dokuwiki
tar czf ~/dokuwiki-conf-$(date +%F).tar.gz -C "$(dirname "$CONF")" conf
ls -lh ~/dokuwiki-conf-*.tar.gz

Nie przechodź dalej, dopóki nie zobaczysz utworzonego archiwum na liście.

Krok 5: podmiana osiemnastu plików

cd "$SRC"
for f in .htaccess acl.auth.php.dist acronyms.conf dokuwiki.php entities.conf \
         interwiki.conf license.php local.php.dist manifest.json mediameta.php \
         mime.conf mysql.conf.php.example plugins.php plugins.required.php \
         scheme.conf smileys.conf users.auth.php.dist wordblock.conf; do
  cp -v "$f" "$CONF/$f"
done

Ta lista jest wyczerpująca. Dokładnie tyle plików dostarcza rdzeń DokuWiki w katalogu conf i żaden z nich nie zawiera Twoich ustawień. Warto zwrócić uwagę na manifest.json, którego w starszej instalacji zwyczajnie nie ma. Plik plugins.php również można spokojnie nadpisać, ponieważ stan włączonych rozszerzeń przechowywany jest w plugins.local.php.

Krok 6: uprawnienia, cache i start

chown 1000:1000 "$CONF"/*
rm -rf "$DATA/cache"/*
docker start dokuwiki
docker logs --tail 30 dokuwiki

Podstaw identyfikatory odczytane w kroku pierwszym. Po uruchomieniu wejdź na ?do=admin&page=config i sprawdź, czy ustawienie syntax jest widoczne z wartością dw.

Pułapka, na której się przejechałem

Jeżeli host korzysta z BusyBoksa zamiast pełnego GNU coreutils, część flag polecenia tar po prostu nie istnieje. Komenda z opcją --wildcards zwróci lakoniczne tar: unrecognized option: wildcards. Z tego powodu w procedurze powyżej rozpakowuję całe archiwum i wskazuję katalog pełną ścieżką, zamiast wycinać pojedynczy podkatalog. Używam wyłącznie flag xzf, które obsługuje każda implementacja.

To dobra ogólna zasada przy pisaniu instrukcji dla nieznanego środowiska. Im mniej egzotycznych przełączników, tym większa szansa, że procedura zadziała u kogoś innego.

Co zrobić po naprawie

Przebudowa indeksu wyszukiwania

W wydaniu „Mort” indeks pełnotekstowy został napisany od nowa i stara struktura jest z nim niezgodna. Bez przebudowy wyszukiwarka będzie zwracać dziwne wyniki:

docker exec dokuwiki php /app/www/public/bin/indexer.php -c

Weryfikacja rozszerzeń

Parser został gruntownie przebudowany, a klasa ModeRegistry jest zupełnie nowa. Starsze pluginy składniowe mogą przestać działać niezależnie od opisanego problemu z konfiguracją. Przejrzyj listę w menedżerze rozszerzeń i zaktualizuj albo wyłącz te, które nie mają wsparcia dla aktualnego wydania. Jeśli używasz szablonu innego niż domyślny, sprawdź również jego zgodność.

Wniosek na przyszłość

Ten incydent dobrze ilustruje pewną pułapkę konteneryzacji. Trwały wolumen kojarzy nam się z danymi użytkownika, tymczasem bardzo często trafiają do niego również pliki należące do aplikacji. Dopóki nic się nie zmienia, wszystko działa. Przy dużym skoku wersji taki katalog staje się jednak zamrożonym fragmentem przeszłości, który zderza się ze świeżym kodem.

Praktyczny wniosek jest prosty. Przy każdej większej aktualizacji warto pobrać upstreamowe wydanie i wykonać diff względem swojego wolumenu, zanim cokolwiek przestanie działać. Zajmuje to dwie minuty, a oszczędza wieczoru z produkcyjną awarią. Jeśli natomiast potrzebujesz kupić sobie czas, przypnij w pliku compose tag poprzedniego wydania zamiast latest i wróć do aktualizacji na spokojnie. Pamiętaj tylko, żeby po cofnięciu wyczyścić zarówno data/cache, jak i data/index.

Najczęstsze pytania

Czy DokuWiki ModeRegistry TypeError oznacza utratę danych?

Nie. Strony wiki leżą w katalogu data/pages i nie są w żaden sposób naruszone. Problem dotyczy wyłącznie warstwy konfiguracji, a wiki wraca do pełnej sprawności natychmiast po uzupełnieniu brakującego ustawienia.

Czy mogę po prostu skasować katalog conf i pozwolić kontenerowi utworzyć go od nowa?

Odradzam. Razem z plikami rdzenia straciłbyś konta użytkowników, listy uprawnień oraz całą własną konfigurację. Podmiana wyłącznie osiemnastu plików rdzenia jest bezpieczniejsza i zajmuje tyle samo czasu.

Czy warto od razu włączyć obsługę Markdown?

To zależy od tego, jak dużo treści już masz. Wartość dw zachowuje dotychczasowe zachowanie i jest bezpiecznym wyborem przy naprawie awarii. Eksperymenty z trybami mieszanymi lepiej przeprowadzić później, na kopii instalacji.

G

Tagi: , ,