PodmanとQuadletのUID・名前解決
Linuxのrootless PodmanとQuadlet、MacのPodman Desktopを使う開発インフラ構築の記録です。Lokiの権限、UIDマッピング、systemd管理、コンテナ内DNSの問題を扱います。
LinuxはQuadlet、MacはPodman Desktop
ローカル開発基盤のコンテナ管理を、ホストごとに決めました。インフラ構築では、起動方式だけでなくUIDと名前解決も合わせる必要がありました。
| ホスト | OS | Podman モード | サービス管理 |
|---|---|---|---|
| Compute Server | Ubuntu 24.04 | rootless | Quadlet(.container → systemd) |
| Storage Server | Ubuntu 24.04 | rootless | Quadlet(.container → systemd) |
| Desktop PC | macOS | Podman Desktop | compose(GUI 管理) |
Linux 2台はrootless Podman + Quadletでsystemd管理します。Macはpodman machineでstorage.home.arpaを解決できなかったため、Podman Desktopにしました。
以下ではQuadletの動作、UID、Lokiの権限、podman unshareとsudoの使い分けを確認します。
Quadlet 検証: Podman 4.9.x で動くか
Ubuntu 24.04のPodman v4.9.3にpodman quadletはありませんが、systemd-generatorによるQuadletは動きました。
確認方法
所定の場所に.containerを置くと、.serviceが生成されます。
systemctl cat node-exporter.service
# /run/systemd/generator/node-exporter.service
# Automatically generated by /usr/lib/systemd/system-generators/podman-system-generator
[Unit]
Description=Prometheus Node Exporter (Quadlet)
After=network-online.target
Wants=network-online.target
SourcePath=/etc/containers/systemd/node-exporter.container
...
Node Exporter の Quadlet ファイル例
ファイルパス: /etc/containers/systemd/node-exporter.container
[Unit]
Description=Prometheus Node Exporter (Quadlet)
After=network-online.target
Wants=network-online.target
[Container]
Image=docker.io/prom/node-exporter:v1.10.1
ContainerName=node-exporter
Network=host
ReadOnly=true
DropCapability=ALL
Volume=/:/host:ro,rslave
Args=--path.rootfs=/host
[Install]
WantedBy=multi-user.target
配置後:
systemctl daemon-reload
systemctl start node-exporter.service
systemctl status node-exporter.service
ENTRYPOINTと引数
最初のExec設定はExec=/bin/node_exporter --path.rootfs=/hostで失敗しました。prom/node-exporterのENTRYPOINTが既に/bin/node_exporterなので、同じコマンドが重複します。設定済みのENTRYPOINTへの引数はArgsで渡します。
systemd 連携の注意点
/run/systemd/generator下に動的生成された Unit はsystemctl enableできない[Install]セクションのWantedBy=multi-user.targetで自動起動を制御する
Rootless UID マッピングの理解
subuidと所有権
rootlessでは、UID 1000のホストユーザーとサブUID(100000〜)を分けます。対応しない所有者のファイルへ通常のユーザー権限ではアクセスできません。
100999:100999のファイルはksh3(UID 1000)から直接操作できません。podman unshareでユーザー名前空間の仮想rootとして扱います。
Loki の permission denied: 実例と分析
rootlessのGrafana Loki(grafana/loki:3.5)でエラーが出ました。
open /loki/index_cache/... .tsdb-tmp: permission denied
/opt/containers/runtime/loki/dataはksh3:1000、0755です。コンテナはloki(UID=10005)で動き、マッピング後の所有者が一致しないため書き込めません。
UID マッピングフロー
ケースごとのUID対応です。
ホスト: ksh3 (UID=1000)
Case A: keep-id なし (イメージ loki=10005)
container root(0) -> host 100000 (subuid開始例)
container loki(10005) -> host 110005
実行UID = 110005 != ディレクトリ所有 1000 → 書けない
Case B: keep-id + loki(罠)
container root(0) -> host 1000
container loki(10005) -> host 110005
実行UID = 110005 != 1000 → 書けない
Case C: keep-id + loki + :U
:U によりホスト側 /data の所有者 chown → 110005
実行UID = 110005 → 書ける
しかしホストユーザー1000は所有者でなくなる → 編集しにくい
Case D: keep-id + User=0 ← 採用
container root(0) -> host 1000
実行UID = 1000 → 所有者一致 → 書ける (ホスト操作性維持)
Case Bではkeep-idを付けても、実行するLokiユーザーはサブUID側に残ります。rootのマッピング変更と、実行ユーザーの変更は別です。
選択肢比較
| 方法 | 仕組み | 動く | ホスト編集 | 最小権限 |
|---|---|---|---|---|
| User=0 + keep-id | root をホスト UID に | OK | OK | 低 |
| loki + ACL | loki UID に ACL 付与 | OK | OK | 中 |
| loki + :U | 自動 chown (所有者 loki) | OK | 低 (sudo 要) | 中 |
| 0777 | 全開放 | OK | OK | 非推奨 |
推奨パターン
- 速く動かしたい / 開発用途 →
UserNS=keep-id+User=0 - 非 root 実行を維持したい → ACL 方式(
UserNS=keep-id不要、User=指定なし)
Loki Quadlet 設定例(User=0 + keep-id 方式)
[Unit]
Description=Grafana Loki (Quadlet - rootless)
After=network-online.target
Wants=network-online.target
[Container]
Image=docker.io/grafana/loki:3.5
ContainerName=loki
Exec=-config.file=/etc/loki/config.yaml
UserNS=keep-id
User=0
Network=host
PublishPort=3100:3100
Volume=/opt/containers/etc/loki:/etc/loki:ro
Volume=/opt/containers/runtime/loki/data:/loki:rw
Volume=/opt/containers/etc/loki/certs:/etc/certs:ro
[Service]
Restart=always
TimeoutStartSec=900s
[Install]
WantedBy=multi-user.target
systemctl --user daemon-reload
systemctl --user restart loki.service
podman logs loki | grep -i permission || echo "permission errors none"
ACL 方式(非 root 維持)
LOKI_UID=$(podman run --rm docker.io/grafana/loki:3.5 id -u)
LOKI_GID=$(podman run --rm docker.io/grafana/loki:3.5 id -g)
setfacl -m u:${LOKI_UID}:rwx /opt/containers/runtime/loki/data
setfacl -R -m u:${LOKI_UID}:rwx /opt/containers/runtime/loki/data
setfacl -d -m u:${LOKI_UID}:rwx /opt/containers/runtime/loki/data
systemctl --user restart loki.service
podman logs loki | grep -i permission || echo "permission errors none"
運用モデル: podman unshare と sudo の3段階
sudoなら所有権の制限を越えて操作できます。rootlessの通常操作とは別の、管理権限を使う経路として扱います。
| フェーズ | 操作 | 方法 |
|---|---|---|
| 通常時 | 一般ユーザーとして操作、コンテナ内ファイルには「触れない」 | Rootless のデフォルト |
| 調整時 | コンテナ内ファイルの微調整、パーミッション変更 | podman unshare |
| 全権が必要な時 | ディレクトリ移設、バックアップ一括操作 | sudo |
読み取り用のバックアップではsudo rsync -aがpodman unshareより単純な場合があります。MinIOの.minio.sysは、-aで所有者情報を維持してコピーしました。
macOS の DNS 問題: CLI から Podman Desktop へ
MacのCLI podman machineでは、Grafanaからstorage.home.arpaのPrometheus / Lokiへ接続できませんでした。
症状
- ホストの Mac からは
curl https://storage.home.arpa:9090が通る - Grafana コンテナ内では名前解決エラーまたは
connection refused - DNS ログに
storage.home.arpa AAAA -> name does not exist
原因: Podman Desktop と CLI の名前解決の違い
| 観点 | Desktop | CLI (machine) |
|---|---|---|
/etc/hosts | ホストと共有 | 独立(VM 内で別管理) |
| DNS 設定反映 | 自動 | 手動 |
| ホスト汚染リスク | 高 | 低 |
| サンドボックス性 | 弱 | 強 |
このCLI環境のVMはホストDNS / hostsを共有せず、home.arpaを解決できませんでした。Composeのdns:も、VMが/etc/resolv.confを生成するため反映されませんでした。
解決策と判断
LinuxはQuadlet + rootlessを維持します。MacはGrafana UI、ブラウザ、VSCodeを使う開発端末なので、内部LANへの接続を優先しました。
MacをPodman Desktopに変えたところ、ホスト側の名前解決がVMへ渡り、storage.home.arpaへ接続できました。extra_hostsの固定指定も追加しました。
services:
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,*.home.arpa
volumes:
- /Users/ksh3/containers/iac/grafana/data:/var/lib/grafana
- /Users/ksh3/containers/iac/grafana/provisioning:/etc/grafana/provisioning:ro
- /Users/ksh3/containers/iac/grafana/certs:/etc/ssl:ro
extra_hosts:
- "storage.home.arpa:10.10.10.3"
depends_on:
- prometheus
注意事項
- Podman 4.9.x には
podman quadletCLI がないが、systemd-generatorが機能するので運用上は問題ない。Podman 5.x で CLI サポートが追加される User=0 + keep-idは開発用途では最短だが、コンテナ内 root 実行なので最小権限ではない。本番寄せなら ACL 方式を検討:U方式はホスト側の所有者がコンテナ UID に変わるため、開発時の操作性が大きく下がる- SELinux 有効環境では Volume に
:Z/:zを追加検討 - NFS /
root_squash環境では:Uやchownが失敗することがある - Podman Desktop は便利だが「安全なサンドボックス」ではなく「便利なブリッジ環境」。名前解決は自分で明示した方が確実
