QuadletでWebとDBから構成されるサービスを実行する

Posted by 雅楽斎 on Monday, March 24, 2025

TOC

WebとDBの2つのコンテナを書いたdocker-compose.ymlから生成した.containerファイルをQuadletで起動するとエラーが出る

弊blogではPodman4.4でマージされたQuadletという仕組みを使ったコンテナ管理を紹介しています。

PodmanをUbuntu24.04で使うにあたってQuadletなるものに触れる

その記事の中で既存のdocker-compose.ymlからPodletというツールを使って.containerファイルを生成してsystemdに登録するという手順でQuadletを使っていますが、webとdbの2つのコンテナが書かれているdocker-compose.ymlからPodletを使って.containerファイルを生成してsystemdに登録するとコンテナの起動でエラーが発生するという事態に陥りました。具体的にはMediawikiですが、Web(PHP)のコンテナからDB(MariaDB)のコンテナに通信ができず、すべてエラーになるというものです。

解決できなかったエラー

ブラウザからMediawikiにアクセスした時に出るこのエラーを解決できませんでした。

MediaWiki internal error.

Original exception: [8270298cd63c99c5079f16cb] / Wikimedia\Rdbms\DBConnectionError: Cannot access the database: php_network_getaddresses: getaddrinfo for mediawiki-database failed: Name or service not known (mediawiki-database)
Backtrace:
from /var/www/html/includes/libs/rdbms/loadbalancer/LoadBalancer.php(1129)
#0 /var/www/html/includes/libs/rdbms/loadbalancer/LoadBalancer.php(796): Wikimedia\Rdbms\LoadBalancer->reportConnectionError()
#1 /var/www/html/includes/libs/rdbms/loadbalancer/LoadBalancer.php(784): Wikimedia\Rdbms\LoadBalancer->getServerConnection(int, string, int)
#2 /var/www/html/includes/libs/rdbms/database/DBConnRef.php(111): Wikimedia\Rdbms\LoadBalancer->getConnectionInternal(int, array, string, int)
#3 /var/www/html/includes/libs/rdbms/database/DBConnRef.php(125): Wikimedia\Rdbms\DBConnRef->ensureConnection()
#4 /var/www/html/includes/libs/rdbms/database/DBConnRef.php(338): Wikimedia\Rdbms\DBConnRef->__call(string, array)
#5 /var/www/html/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php(763): Wikimedia\Rdbms\DBConnRef->selectField(array, string, array, string, array, array)
#6 /var/www/html/includes/language/LCStoreDB.php(65): Wikimedia\Rdbms\SelectQueryBuilder->fetchField()
#7 /var/www/html/includes/language/LocalisationCache.php(566): LCStoreDB->get(string, string)
#8 /var/www/html/includes/language/LocalisationCache.php(612): LocalisationCache->isExpired(string)
#9 /var/www/html/includes/language/LocalisationCache.php(523): LocalisationCache->initLanguage(string)
#10 /var/www/html/includes/language/LocalisationCache.php(403): LocalisationCache->loadSubitem(string, string, string)
#11 /var/www/html/includes/language/LocalisationCache.php(419): LocalisationCache->getSubitem(string, string, string)
#12 /var/www/html/includes/language/MessageCache.php(1267): LocalisationCache->getSubitemWithSource(string, string, string)
#13 /var/www/html/includes/language/MessageCache.php(1209): MessageCache->getMessageForLang(LanguageEn, string, bool, array)
#14 /var/www/html/includes/language/MessageCache.php(1106): MessageCache->getMessageFromFallbackChain(LanguageEn, string, bool)
#15 /var/www/html/includes/Message/Message.php(1552): MessageCache->get(string, bool, LanguageEn, string)
#16 /var/www/html/includes/Message/Message.php(1035): MediaWiki\Message\Message->fetchMessage()
#17 /var/www/html/includes/Message/Message.php(1125): MediaWiki\Message\Message->format(string)
#18 /var/www/html/includes/title/MalformedTitleException.php(61): MediaWiki\Message\Message->text()
#19 /var/www/html/includes/title/MediaWikiTitleCodec.php(93): MediaWiki\Title\MalformedTitleException->__construct(string, string, array)
#20 /var/www/html/includes/title/MediaWikiTitleCodec.php(403): MediaWiki\Title\MediaWikiTitleCodec::MediaWiki\Title\{closure}(string, string)
#21 /var/www/html/includes/title/Title.php(2744): MediaWiki\Title\MediaWikiTitleCodec->splitTitleString(string, int)
#22 /var/www/html/includes/title/Title.php(503): MediaWiki\Title\Title->secureAndSplit(string)
#23 /var/www/html/includes/actions/ActionEntryPoint.php(241): MediaWiki\Title\Title::newFromURL(string)
#24 /var/www/html/includes/actions/ActionEntryPoint.php(332): MediaWiki\Actions\ActionEntryPoint->parseTitle(MediaWiki\Request\WebRequest)
#25 /var/www/html/includes/actions/ActionEntryPoint.php(94): MediaWiki\Actions\ActionEntryPoint->getTitle()
#26 /var/www/html/includes/MediaWikiEntryPoint.php(200): MediaWiki\Actions\ActionEntryPoint->execute()
#27 /var/www/html/index.php(58): MediaWiki\MediaWikiEntryPoint->run()
#28 {main}

これはpodman-composepodman generate systemdで出力したファイルでは発生しなかった問題で、Quadletでのサービス管理に移行する上で解決したかったので色々トライして別解を導きました。

podファイルを使う

stackoverflowでMediawikiをQuadletで動かしてた人がいて、今までやっていたcontainerファイルじゃなくてpodファイルで実現していたので同じように書いたら所望の動作をするようにはなりました。

linux - rootless podman quadlet webserver not reachable from host - Stack Overflow

Ubuntu 24.04でpodファイルを使い、OSの起動時に自動実行するには→Ubuntu 25.04からpodmanパッケージを借りる

このpodを使うという解決法、QuadletでのpodファイルのサポートがそもそもPodman5.0以降であることと、後述するOS起動時に自動起動するために指定が必要なユニットであるpodman-user-wait-network-online.serviceがPodman5.0には存在しないため、最終的にUbuntuに収録されているpodmanパッケージはUbuntu 25.04から借りてくる必要がある、というのが現状です。

また、本記事は現在Ubuntu25.04のpodmanパッケージである5.4.1ではなく5.4.0の時に確認したため、動作が変わる可能性はあります。

安定したファイルの一式

docker-compose.yml(元になったもの)

# MediaWiki with MariaDB
#
# Access via "http://localhost:8080"
#   (or "http://$(docker-machine ip):8080" if using docker-machine)
version: '3'
name: mediawiki
services:
  mediawiki:
    image: mediawiki:1.43 # lts old:1.39
      #contaier_name: mediawiki-web
    restart: always
    ports:
      - 18080:80
        #links:
        #- mediawiki-database
    volumes:
      - /var/containers/mediawiki/mediawiki-docker-images/images:/var/www/html/images
      - /var/containers/mediawiki/mediawiki-docker-LocalSettingsPhp/LocalSettings.php:/var/www/html/LocalSettings.php
    networks:
      - mediawikinetwork
  # This key also defines the name of the database host used during setup instead of the default "localhost"
  mediawiki-database:
    image: mariadb:10.11
      #container_name: mediawiki-db
    restart: always
    environment:
      # @see https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/DefaultSettings.php
      MYSQL_DATABASE: my_wiki
      MYSQL_USER: wikiuser
      MYSQL_PASSWORD: example
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
    ports:
      - "3306:3306"
    volumes:
      - /var/containers/mediawiki/mediawiki-docker-db/db:/var/lib/mysql
    networks:
      - mediawikinetwork

networks:
  mediawikinetwork:
    driver: bridge
    internal: false
      #name: mediawikinetwork

pod

mediawiki.pod

[Unit]
After=network-online.target podman-user-wait-network-online.service
Requires=podman-user-wait-network-online.service

[Pod]
PodName=Mediawiki
Network=mediawiki.network
PublishPort=18080:80
PublishPort=3306:3306

[Install]
# Start by default on boot
WantedBy=multi-user.target default.target

mediawiki-mediawiki.container

厳密にはmariadbが起動した後に実行されるべきなので、RequiresとAfterにmediawiki-databaseを指定した方が良さそうですがpodの中のcontainerを指定する方法は未確認です。

[Unit]
After=network-online.target

[Container]
Image=mediawiki:1.43
ContainerName=mediawiki-mediawiki
Pod=mediawiki.pod
Volume=/var/containers/mediawiki/mediawiki-docker-images/images:/var/www/html/images
Volume=/var/containers/mediawiki/mediawiki-docker-LocalSettingsPhp/LocalSettings.php:/var/www/html/LocalSettings.php

[Service]
Restart=always

mediawiki-database.container

[Unit]
After=network-online.target

[Container]
Environment=MYSQL_DATABASE=my_wiki MYSQL_USER=wikiuser MYSQL_PASSWORD=example MYSQL_RANDOM_ROOT_PASSWORD=yes
Image=mariadb:10.11
ContainerName=mediawiki-database
Pod=mediawiki.pod
Volume=/var/containers/mediawiki/mediawiki-docker-db/db:/var/lib/mysql

[Service]
Restart=always

mediawiki.network

[Unit]
After=network-online.target

[Network]
Driver=bridge

使うパラメータの整理

これらファイルの中で指定している各パラメータの定義場所は以下の通りです。

ファイル名パラメータ参照場所
mediawiki.podNetwork=mediawiki.networkmediawiki.network(ファイル名)
PublishPort=18080:80mediawiki-mediawiki.containerがexposeするポート番号
PublishPort=3306:3306mediawiki-database.containerがexposeするポート番号
mediawiki-mediawiki.containerImage=mediawiki:1.43dokerhubのイメージ名とタグ
Pod=mediawiki.podpodファイル名
mediawiki-database.containerImage=mariadb:10.11dockerhubのイメージ名とタグ
Pod=mediawiki.podpodファイル名
Environment=MYSQL_DATABASE=my_wiki MYSQL_USER=wikiuser MYSQL_PASSWORD=exampleLocalSettings.phpの$wgDBname、$wgDBuser、$wgDBpassword
LocalSettings.php$wgDBserver = “mediawiki-database”;mediawiki-database.container(ファイル名) または ContainerName=mediawiki-database?

Ubuntu24.04にUbuntu25.04のpodmanパッケージファイルをインストールする

前述したように、Ubuntu25.04のパッケージをインストールしますが、podmanパッケージの他に24.04には存在しないパッケージファイルも一緒に(あるいは事前に)インストールする必要があります。最終的にインストールが必要なファイルは以下のとおりです。執筆時時点でバージョンが違うものがあります。

  • libgpgme11t64_1.24.2-1ubuntu2_arm64.deb
  • libsubid5_4.16.0-7ubuntu1_arm64.deb
  • podman_5.4.0+ds1-1_arm64.deb

これらのファイルをダウンロードしたら、aptコマンドでインストールします。

# apt install ./libgpgme11t64_1.24.2-1ubuntu2_arm64.deb ./libsubid5_4.16.0-7ubuntu1_arm64.deb ./podman_5.4.0+ds1-1_arm64.deb

podファイルとcontainerファイルとnetworkファイルをsystemdに登録する

前述した4ファイルを~/.config/containers/systemd/等のsystemdで参照するディレクトリにコピーします。なお、このディレクトリにある任意のサブディレクトリはsystemdの読み込み対象になるので、今回のように複数ファイルで1サービスを定義する場合はサブディレクトリを作成してその中に格納すると管理が楽でしょう。

4ファイルを格納したら、いつも通り以下のコマンドでsystemdに反映します。今回は一般ユーザーの権限で動作させるため、--user引数も指定します。

$ systemctl --user daemon-reload

podファイルを指定して、サービスを起動します。

$ systemctl --user start mediawiki-pod.service 
$ systemctl --user status mediawiki-pod.service 
● mediawiki-pod.service
     Loaded: loaded (/home/hogehoge/.config/containers/systemd/mediawiki/mediawiki.pod; generated)
     Active: active (running) since Thu 2025-03-12 22:29:19 JST; 2h 30min ago
   Main PID: 2397 (conmon)
      Tasks: 17 (limit: 18505)
     Memory: 38.6M (peak: 49.3M)
        CPU: 946ms
     CGroup: /user.slice/user-1001.slice/user@1001.service/app.slice/mediawiki-pod.service
             ├─2365 rootlessport
             ├─2380 rootlessport-child
             └─2397 /usr/bin/conmon --api-version 1 -c cdfe439a9769e61552945da2186ffb00ba70350867d55c7a0bf681f4a99ab566 -u cdfe439a9769e61552945da2186ffb00ba70350867d55c7a0bf681f4a99ab566 -r /usr/bin/crun -b /var/containers/storage_hogeho>

OS起動時の自動起動について

以前弊blogにもQuadletについてOS起動時の自動起動はInstallセクションにWantedBy=multi-user.target default.targetを記述すると記載しました。

PodmanをUbuntu24.04で使うにあたってQuadletなるものに触れる

ですが、podファイルの場合はそうではなく、podman-user-wait-network-online.serviceの終了後に実行する必要があるようです。

Docker ComposeからPodmanに移行する

今回mediawiki.podに指定済みのため、OSの自動起動時に実行されるターゲットに指定されています。

$ systemctl --user list-dependencies default.target 
default.target
● ├─docker.service
● ├─mediawiki-pod.service
○ ├─podman-auto-update.service
○ ├─podman-clean-transient.service
● ├─podman-restart.service
× ├─podman.service
● ├─syncthing.service
● ├─wikijs.service
● └─basic.target
●   ├─paths.target
●   ├─sockets.target
●   │ ├─dbus.socket
●   │ ├─dirmngr.socket
●   │ ├─gpg-agent-browser.socket
●   │ ├─gpg-agent-extra.socket
●   │ ├─gpg-agent-ssh.socket
●   │ ├─gpg-agent.socket
●   │ ├─keyboxd.socket
●   │ ├─pk-debconf-helper.socket
●   │ ├─podman.socket
●   │ └─snapd.session-agent.socket
●   └─timers.target
●     ├─launchpadlib-cache-clean.timer
●     └─podman-auto-update.timer

雑感

今回、元々はdocker-compose.ymlからcontainerファイルを生成するpodletでやれば問題なくできるんじゃないかと思っていましたが全然そんなことなく、原因を追っかけるとpodmanのissueにぶつかって、podmanのchangelogにそれっぽく見える変更が書かれていたりとQuadlet周辺はまだまだ発展途上という印象を強く受けました。

podman自体もRedhatが開発しているものなのでターゲットディストロは当然RHELだったりFedoraだったりする訳で、そっちの最新バージョンと同期しているわけでもないUbuntuで使うのはまだ時期尚早で、2〜3年経つ(かLTSのbackportsに最新バージョンが同期される)くらいじゃないと常用は難しいのかもなと思いました。それまではバグなのか仕様なのかの判断に時間がかかる日々が続きそうです。

スポンサーリンク


comments powered by Disqus