コンテナ開発用の環境をDebian系+DockerからRedHat系+Podmanにしようとしてるので
お試し環境構築忘備録
- プライベートレジストリ(Docker Registry)
- クロスビルド環境(マルチプラットフォーム)
rootless生かしてうまい具合にユーザー切り分けて運用したい
当方Dockerしか触ったことない
DockerとPodmanの違い(n番煎じなので折りたたみ)
- Dockerのようにrootのdaemonが常駐しない
- 起動時のコンテナ立ち上げは
systemdを使う - Podman の --restart は「Podman が再起動したとき」にコンテナをどうするか程度の意味なので、基本的に不要
- 起動時のコンテナ立ち上げは
- sudoで
rootful、つけないとrootlessで動作する
rootful、rootlessの各ユーザは環境・設定を共有しない
環境をまたいでコンテナ間でやり取りする場合ホストポートをつかう等必要となる- デフォルトnetworkのNameは
podmanだがコンテナ名での名前解決ができない- コンテナ名での名前解決は同じカスタムネットワーク内か同じPod内のみ
- rootlessの場合root権限が必要なポートである1024未満のポートが利用できない
利用したい場合はホスト側の設定で80⇒8080のようなポートフォワーディングを行う
※カーネルの設定を変える術はあるが非推奨
- デフォルトnetworkのNameは
-
Podという概念がある(Kubernetes由来?)- 1つのPodにまとめたコンテナは同じホストに存在するようなふるまい
- 共通のvolumeをつくれる
- localhostでアクセスできる
- portを競合させることができない
- デザインパターン、アンチパターンがあるので確認
- 1つのPodにまとめたコンテナは同じホストに存在するようなふるまい
方針
- Cockpitでサーバー管理
- 原則rootlessのみ
以下ユーザーを準備 sudo権限を与えない-
svcuser サービス用ユーザー
-
systemdでコンテナ起動設定 -
login ctl enable-linger USERNAMEでセッションが終わった後もsystemdで起動したプロセスを終了させないよう設定
-
-
builder 一般ユーザー
- ビルド作業、テスト用
-
svcuser サービス用ユーザー
- 今回Podを用いるデザインパターンなし
環境
- WSL バージョン: 2.6.1.0
- カーネル バージョン: 6.6.87.2-1
- Windows バージョン: 10.0.26100.6584
- AlmaLinux 10.0
- cockpit.x86_64 334.1-1.el10_0
- podman.x86_64 6:5.4.0-13.el10_0
- buildah.x86_64 2:1.39.4-2.el10_0
Install AlmaLinux on WSL2
# 今回更新しておく
wsl update
wsl --set-default-version 2
# インストールできるディストリビューション確認
wsl --list --online
wsl --install -d AlmaLinux-10
以降AlmaLinux内
初期設定
1.パッケージ一覧取得とセキュリティ更新
$ dnf list --all
$ dnf check-update
# dnf upgrade --security
2.日本語化
$ dnf -y install langpacks-ja
# localectl set-locale LANG=ja_JP.UTF-8
$ source /etc/locale.conf
$ date
2025年 10月 4日 土曜日 13:16:19 JST
WSLの場合TimeZone設定済
パッケージ導入
Cockpit - サーバー管理ツール
# dnf install cockpit
# systemctl enable --now cockpit.socket
https://localhost:9090またはhttps://${severip}:9090でアクセス

アプリケーションからPodman用のアドオンをインストールすることができる
Podman - コンテナ実行・管理エンジン
# dnf install podman
WSL2のissue対応
Podmanでコンテナをカスタムnetworkに参加させる際やQEMU導入の際に以下エラーが発生
internal:0:0-0: Error: Could not process rule: No such file or directory
Error: netavark: nftables error: nft did not return successfully while applying ruleset
WSL2側のissueとして実施日の前日にもコメントが行われていた
https://github.com/containers/podman/issues/25201
発生した際の対応策
nftablesでなくiptablesを使うように設定
/etc/containers/containers.conf
[network]
firewall_driver="iptables"
Buildah - コンテナビルドツール
# dnf install buildah
QEMU
クロスビルドに対応するためQEMUをインストールする
古いドキュメントだとqemu-user-staticが案内されているが、現在は提供されていない。
コンテナ経由で作成する。
https://docs.docker.com/build/building/multi-platform/#qemu
バイナリが/proc/sys/fs/binfmt_misc/に作成されればOKなのでrootfulで1回だけ動かす。
sudo podman run --privileged --rm tonistiigi/binfmt --install all
/proc/(仮想ファイルシステム) 内に作られるため再起動すると内容が失われる。
永続化のためにsystemdユニットファイルを作る必要があるがpodman generate systemd が対応していないため
自力で作る必要がある。
1.ユニットファイルを作成
rootコンテナとして起動するように/etc/systemd/system/binfmt-container.serviceを作成
[Unit]
Description=Register binfmt_misc using tonistiigi/binfmt
After=network.target
Requires=proc-sys-fs-binfmt_misc.mount
[Service]
Type=oneshot
ExecStartPre=/bin/mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
ExecStart=/usr/bin/podman run --rm --privileged tonistiigi/binfmt --install all
RemainAfterExit=true
[Install]
WantedBy=multi-user.target
-
ExecStartPre=/bin/mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
先にマウントしないとpodman runが成功しても作成されなかった 起動順の問題みたい -
oneshot起動後すぐに終了する -
RemainAfterExit=trueサービス終了後も「アクティブとして保持」
2.ユニットを有効化して起動
$ sudo systemctl daemon-reexec
$ sudo systemctl daemon-reload
$ sudo systemctl enable binfmt-container.service
$ sudo systemctl start binfmt-container.service
再起動後確認
$ sudo systemctl status binfmt-container.service
$ ls -a /proc/sys/fs/binfmt_misc/
. WSLInterop qemu-arm qemu-mips64 qemu-ppc64le qemu-s390x status
.. qemu-aarch64 qemu-loongarch64 qemu-mips64el qemu-riscv64 register
qemu-* のエントリがあれば、そのアーキテクチャがエミュレーション可能。
ユーザー作成
- サービス用ユーザーを作成
-
/srv以下にサービスのvolumeを作るため権限を与える - enable-linger systemdで起動したプロセスはログアウト後も終了させない
# useradd -m -s /bin/bash svcuser
# passwd svcuser
# chown svcuser:svcuser /srv
$ login ctl enable-linger svcuser
- ビルダーユーザーを作成
# useradd -m -s /bin/bash builder
# passwd builder
コンテナ運用環境構築 (svcuserで作業)
カスタムnetworkを作成
$ podman network create infra-net
$ podman network ls
NETWORK ID NAME DRIVER
4e23f5ec6468 infra-net bridge
2f259bab93aa podman bridge
プライベートレジストリ作成
1.Registryコンテナ作成
volume用ディレクトリ作成
$ mkdir /srv/registry
$ podman run -d \
--name registry \
--network infra-net \
-p 5000:5000 \
-v /srv/registry:/var/lib/registry:z \
docker.io/library/registry:3
複数レジストリがあるのでdocker.io/library/registryと明示するのがよい。
コンテナをCockpitで見ることができる。Cockpit上でコンテナを作成することもできる。

http://${server_ip}/v2/_catalogまたはhttp://localhost:5000/v2/_catalogにアクセスすることでカタログが参照できる。
2.コンテナーレジストリの設定
ローカルでコンテナレジストリを参照するためのPodmanの設定を行う
RedHat公式ドキュメントが詳しい
ここだけルートユーザー# ローカルのプライベートレジストリにTLSなしでアクセスするように/etc/containers/registries.confを編集
[[registry]]
location="localhost:5000"
insecure=true
podman infoでレジストリが追加されているのがわかる
$ podman info
...
registries:
localhost:5000:
Blocked: false
Insecure: true
Location: localhost:5000
...
これでpush/pullが行える
$ podman push localhost:5000/myimage:latest
$ podman pull localhost:5000/myimage:latest
3. コンテナ永続化(systemd)
- コンテナが起動している場合停止
- 作業ディレクトリにsystemd ユニットファイル作成
$ podman generate systemd --name registry --files --new $ ls container-registry.service - ユニットファイルをユーザー用 systemd に配置
$ mkdir -p ~/.config/systemd/user $ mv container-registry.service ~/.config/systemd/user/ - systemd にリロードして有効化
$ systemctl --user daemon-reload $ systemctl --user enable --now container-registry.service- enable → ログイン時に自動起動
- now → 今すぐ起動
- 確認
$ systemctl --user status container-registry.service ● container-registry.service - Podman container-registry.service Loaded: loaded (/home/svcuser/.config/systemd/user/container-registry.service; enabled; preset: disabled) Active: active (running) since Sun 2025-10-05 19:04:32 JST; 8s ago
コンテナ開発環境構築 (builderで作業)
クロスビルド
$ pwd
/home/builder/podman-build/images/hello
$ cat Dockerfile
FROM alpine:latest
CMD ["echo", "Hello, World!"]
--- amd64版をビルド
$ podman build --platform linux/arm64 --tag test/hello:amd64 .
--- arm64版をビルド
$ podman build --platform linux/arm64 --tag test/hello:arm64 .
または
--- amd64版をビルド
$ buildah bud --arch amd64 -t test/hello2:amd64 .
--- arm64版をビルド
$ buildah bud --arch arm64 -t test/hello2:arm64 .
--- 確認
$ podman inspect localhost/test/hello:amd64 | grep Architecture
"Architecture": "amd64",
$ podman inspect localhost/test/hello:arm64 | grep Architecture
"Architecture": "arm64",
マルチアーキテクチャイメージのマニフェストを作るとCockpitのPodman管理画面がエラーとなる
マニフェストを削除すれば復旧する
マルチアーキテクチャーイメージのビルド(失敗)
RHELのマニュアル見るとpodman buildでのビルド方法が書いてある
4.9. マルチアーキテクチャーイメージのビルド
$ podman build --platform linux/arm64,linux/amd64 --manifest test/hello .
[linux/arm64] STEP 1/2: FROM alpine:latest
...
[linux/arm64] COMMIT
--> d8874c695a2e
[linux/amd64] STEP 1/2: FROM alpine:latest
...
[linux/amd64] COMMIT
--> ebd3963ef97e
ebd3963ef97e220d6bcdf944d51fe06e9349d306c74ad8ba3e8288fedca59c4f
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> ebd3963ef97e 3 minutes ago 8.6 MB
localhost/test/hello latest af7fd5600141 3 minutes ago 1.05 kB
<none> <none> d8874c695a2e 3 minutes ago 8.79 MB
docker.io/library/alpine latest 9234e8fb04c4 2 months ago 8.61 MB
📦 ebd3963ef97e ← amd64用のイメージ
📦 d8874c695a2e ← arm64用のイメージ
📦 af7fd5600141 ← マニフェスト (両方をまとめた仮想イメージ)
ができた
しかし
- マニフェストの中を見てもarm64がいない
- cockpit-podmanがクラッシュする
上記イメージをpodman rmiで削除すれば復旧する
buildahでも同様
--- amd64版をビルド
$ buildah bud --arch amd64 -t test/hello:amd64 .
--- arm64版をビルド
$ buildah bud --arch arm64 -t test/hello:arm64 .
--- マニフェスト作成(この段階でcockpit-podmanでイメージが見れない) ---
$ buildah manifest create test/hello
--- マニフェスト追加 ---
$ buildah manifest add test/hello test/hello:amd64
$ buildah manifest add test/hello test/hello:arm64
プライベートレジストリへのpush
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test/hello amd64 8f12cba7d171 4 seconds ago 8.6 MB
localhost/test/hello arm64 c8752c6caa0f 17 seconds ago 8.79 MB
docker.io/library/alpine latest 9234e8fb04c4 2 months ago 8.61 MB
$ podman tag localhost/test/hello:amd64 localhost:5000/test/hello:amd64
$ podman tag localhost/test/hello:arm64 localhost:5000/test/hello:arm64
$ podman push localhost:5000/test/hello:amd64
Getting image source signatures
Copying blob 418dccb7d85a done |
Copying config 8f12cba7d1 done |
Writing manifest to image destination
$ podman push localhost:5000/test/hello:arm64
Getting image source signatures
Copying blob 0b83d017db6e done |
Copying config c8752c6caa done |
Writing manifest to image destination
確認
$ curl -s http://localhost:5000/v2/_catalog
{"repositories":["test/hello"]}
$ curl -s http://localhost:5000/v2/test/hello/tags/list
{"name":"test/hello","tags":["amd64","arm64"]}
マルチアーキテクチャイメージ失敗
$ podman manifest create localhost/test/hello:latest
$ podman manifest add localhost/test/hello:latest localhost/test/hello:amd64
$ podman tag localhost/test/hello:latest localhost:5000/test/hello:latest
$ podman push localhost:5000/test/hello:latest
Getting image source signatures
Copying blob 5f70bf18a086 done |
Copying blob 418dccb7d85a done |
Copying config bbb84b0839 done |
Writing manifest to image destination
$ curl -X GET http://localhost:5000/v2/_catalog
{"repositories":["test/hello"]}
[hijiri@powerPC srv]$ curl -X GET http://localhost:5000/v2/test/hello/manifests/latest
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"OCI manifest found, but accept header does not support OCI manifests"}]}
イメージが消えなくなったのですべてのイメージを削除
podman system prune -a --force